| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| #include "cmExportBuildPackageInfoGenerator.h" | |
| #include <cassert> | |
| #include <functional> | |
| #include <map> | |
| #include <utility> | |
| #include <vector> | |
| #include <cmext/string_view> | |
| #include <cm3p/json/value.h> | |
| #include "cmAlgorithms.h" | |
| #include "cmDiagnosticContext.h" | |
| #include "cmDiagnostics.h" | |
| #include "cmGenExContext.h" | |
| #include "cmGeneratorExpression.h" | |
| #include "cmGeneratorFileSet.h" | |
| #include "cmGeneratorTarget.h" | |
| #include "cmList.h" | |
| #include "cmPackageInfoArguments.h" | |
| #include "cmStringAlgorithms.h" | |
| #include "cmTargetTypes.h" | |
| cmExportBuildPackageInfoGenerator::cmExportBuildPackageInfoGenerator( | |
| cmPackageInfoArguments arguments, cmDiagnosticContext context) | |
| : cmExportBuildFileGenerator(std::move(context)) | |
| , cmExportPackageInfoGenerator(std::move(arguments)) | |
| { | |
| this->SetNamespace(cmStrCat(this->GetPackageName(), "::"_s)); | |
| } | |
| bool cmExportBuildPackageInfoGenerator::GenerateMainFile(std::ostream& os) | |
| { | |
| if (!this->CollectExports([&](cmGeneratorTarget const*) {})) { | |
| return false; | |
| } | |
| if (!this->CheckPackage()) { | |
| return false; | |
| } | |
| Json::Value root = this->GeneratePackageInfo(); | |
| root["cps_path"] = "@prefix@"; | |
| Json::Value& components = root["components"]; | |
| // Create all the imported targets. | |
| for (auto const& exp : this->Exports) { | |
| cmGeneratorTarget* const target = exp.Target; | |
| cm::TargetType targetType = this->GetExportTargetType(target); | |
| Json::Value* const component = | |
| this->GenerateImportTarget(components, target, targetType); | |
| if (!component) { | |
| return false; | |
| } | |
| ImportPropertyMap properties; | |
| if (!this->PopulateInterfaceProperties(target, properties)) { | |
| return false; | |
| } | |
| this->PopulateInterfaceLinkLibrariesProperty( | |
| target, cmGeneratorExpression::InstallInterface, properties); | |
| if (targetType != cm::TargetType::INTERFACE_LIBRARY) { | |
| auto configurations = Json::Value{ Json::objectValue }; | |
| // Add per-configuration properties. | |
| for (std::string const& c : this->Configurations) { | |
| this->GenerateInterfacePropertiesConfig(configurations, target, c); | |
| } | |
| if (!configurations.empty()) { | |
| (*component)["configurations"] = configurations; | |
| } | |
| } | |
| // De-duplicate include directories prior to generation. | |
| auto it = properties.find("INTERFACE_INCLUDE_DIRECTORIES"); | |
| if (it != properties.end()) { | |
| auto list = cmList{ it->second }; | |
| list = cmList{ list.begin(), cmRemoveDuplicates(list) }; | |
| properties["INTERFACE_INCLUDE_DIRECTORIES"] = list.to_string(); | |
| } | |
| // Set configuration-agnostic properties for component. | |
| this->GenerateInterfaceProperties(*component, target, properties); | |
| this->GenerateTargetFileSets(*component, target); | |
| } | |
| this->GeneratePackageRequires(root); | |
| // Write the primary packing information file. | |
| this->WritePackageInfo(root, os); | |
| bool result = true; | |
| return result; | |
| } | |
| void cmExportBuildPackageInfoGenerator::GenerateInterfacePropertiesConfig( | |
| Json::Value& configurations, cmGeneratorTarget* target, | |
| std::string const& config) | |
| { | |
| std::string const& suffix = PropertyConfigSuffix(config); | |
| ImportPropertyMap properties; | |
| assert(this->GetExportTargetType(target) != | |
| cm::TargetType::INTERFACE_LIBRARY); | |
| this->SetImportLocationProperty(config, suffix, target, properties); | |
| if (properties.empty()) { | |
| return; | |
| } | |
| this->SetImportDetailProperties(config, suffix, target, properties); | |
| // TODO: PUBLIC_HEADER_LOCATION | |
| Json::Value component = | |
| this->GenerateInterfaceConfigProperties(suffix, properties); | |
| this->GenerateCxxModules(component, target, this->FileDir, config); | |
| if (!component.empty()) { | |
| configurations[config.empty() ? std::string{ "noconfig" } : config] = | |
| std::move(component); | |
| } | |
| } | |
| void cmExportBuildPackageInfoGenerator::GenerateTargetFileSets( | |
| Json::Value& fileSets, cmGeneratorTarget const* target, | |
| cmGeneratorFileSet const* fileSet, cmTargetExport const* /*targetExport*/, | |
| std::string const& type) const | |
| { | |
| cm::GenEx::Context context{ target->LocalGenerator, {} }; | |
| std::map<std::string, std::vector<std::string>> files; | |
| auto eval = [&files](std::string&& baseDir, std::string&& relPath, | |
| std::string&& /*file*/) { | |
| files[std::move(baseDir)].emplace_back(std::move(relPath)); | |
| }; | |
| if (fileSet->EvaluateFiles(context, target, eval)) { | |
| this->IssueDiagnostic( | |
| cmDiagnostics::CMD_AUTHOR, | |
| cmStrCat("The \""_s, target->GetName(), | |
| "\" target's interface file set \""_s, fileSet->GetName(), | |
| "\" of type \""_s, fileSet->GetType(), | |
| "\" contains context-sensitive information, which is not " | |
| "supported. The file set will not be exported."_s)); | |
| return; | |
| } | |
| for (auto const& i : files) { | |
| this->GenerateTargetFileSet(fileSets, fileSet, type, i.first, i.second); | |
| } | |
| } | |
| std::string cmExportBuildPackageInfoGenerator::GetCxxModulesDirectory() const | |
| { | |
| return this->CxxModulesDirectory; | |
| } |