mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-16 12:11:04 -06:00
CPS package metadata involves a fair amount of passing around a particular set of values, as well as shared argument handling, which is only going to increase as additional features are added. In order to reduce code duplication (now and going forward), create a helper class to handle the shared argument parsing and to serve as a container to pass metadata values.
196 lines
5.5 KiB
C++
196 lines
5.5 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file LICENSE.rst or https://cmake.org/licensing for details. */
|
|
#include "cmExportInstallPackageInfoGenerator.h"
|
|
|
|
#include <memory>
|
|
#include <set>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <cm3p/json/value.h>
|
|
|
|
#include "cmExportSet.h"
|
|
#include "cmGeneratorExpression.h"
|
|
#include "cmGeneratorTarget.h"
|
|
#include "cmInstallExportGenerator.h"
|
|
#include "cmLocalGenerator.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmPackageInfoArguments.h"
|
|
#include "cmStateTypes.h"
|
|
#include "cmStringAlgorithms.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmTarget.h"
|
|
#include "cmTargetExport.h"
|
|
|
|
cmExportInstallPackageInfoGenerator::cmExportInstallPackageInfoGenerator(
|
|
cmInstallExportGenerator* iegen, cmPackageInfoArguments arguments)
|
|
: cmExportPackageInfoGenerator(std::move(arguments))
|
|
, cmExportInstallFileGenerator(iegen)
|
|
{
|
|
}
|
|
|
|
std::string cmExportInstallPackageInfoGenerator::GetConfigImportFileGlob()
|
|
const
|
|
{
|
|
std::string glob = cmStrCat(this->FileBase, "@*", this->FileExt);
|
|
return glob;
|
|
}
|
|
|
|
std::string const& cmExportInstallPackageInfoGenerator::GetExportName() const
|
|
{
|
|
return this->GetPackageName();
|
|
}
|
|
|
|
bool cmExportInstallPackageInfoGenerator::GenerateMainFile(std::ostream& os)
|
|
{
|
|
std::vector<cmTargetExport const*> allTargets;
|
|
{
|
|
auto visitor = [&](cmTargetExport const* te) { allTargets.push_back(te); };
|
|
|
|
if (!this->CollectExports(visitor)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!this->CheckDefaultTargets()) {
|
|
return false;
|
|
}
|
|
|
|
Json::Value root = this->GeneratePackageInfo();
|
|
Json::Value& components = root["components"];
|
|
|
|
// Compute the relative import prefix for the file
|
|
std::string const& packagePath = this->GenerateImportPrefix();
|
|
if (packagePath.empty()) {
|
|
return false;
|
|
}
|
|
root["cps_path"] = packagePath;
|
|
|
|
// Create all the imported targets.
|
|
bool requiresConfigFiles = false;
|
|
for (cmTargetExport const* te : allTargets) {
|
|
cmGeneratorTarget* gt = te->Target;
|
|
cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
|
|
|
|
Json::Value* const component =
|
|
this->GenerateImportTarget(components, gt, targetType);
|
|
if (!component) {
|
|
return false;
|
|
}
|
|
|
|
ImportPropertyMap properties;
|
|
if (!this->PopulateInterfaceProperties(te, properties)) {
|
|
return false;
|
|
}
|
|
this->PopulateInterfaceLinkLibrariesProperty(
|
|
gt, cmGeneratorExpression::InstallInterface, properties);
|
|
|
|
if (targetType != cmStateEnums::INTERFACE_LIBRARY) {
|
|
requiresConfigFiles = true;
|
|
}
|
|
|
|
// Set configuration-agnostic properties for component.
|
|
this->GenerateInterfaceProperties(*component, gt, properties);
|
|
}
|
|
|
|
this->GeneratePackageRequires(root);
|
|
|
|
// Write the primary packing information file.
|
|
this->WritePackageInfo(root, os);
|
|
|
|
bool result = true;
|
|
|
|
// Generate an import file for each configuration.
|
|
if (requiresConfigFiles) {
|
|
for (std::string const& c : this->Configurations) {
|
|
if (!this->GenerateImportFileConfig(c)) {
|
|
result = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void cmExportInstallPackageInfoGenerator::GenerateImportTargetsConfig(
|
|
std::ostream& os, std::string const& config, std::string const& suffix)
|
|
{
|
|
Json::Value root;
|
|
root["name"] = this->GetPackageName();
|
|
root["configuration"] = config;
|
|
|
|
Json::Value& components = root["components"];
|
|
|
|
for (auto const& te : this->GetExportSet()->GetTargetExports()) {
|
|
// Collect import properties for this target.
|
|
if (this->GetExportTargetType(te.get()) ==
|
|
cmStateEnums::INTERFACE_LIBRARY) {
|
|
continue;
|
|
}
|
|
|
|
ImportPropertyMap properties;
|
|
std::set<std::string> importedLocations;
|
|
|
|
this->PopulateImportProperties(config, suffix, te.get(), properties,
|
|
importedLocations);
|
|
|
|
Json::Value component =
|
|
this->GenerateInterfaceConfigProperties(suffix, properties);
|
|
if (!component.empty()) {
|
|
components[te->Target->GetExportName()] = std::move(component);
|
|
}
|
|
}
|
|
|
|
this->WritePackageInfo(root, os);
|
|
}
|
|
|
|
std::string cmExportInstallPackageInfoGenerator::GenerateImportPrefix() const
|
|
{
|
|
std::string expDest = this->IEGen->GetDestination();
|
|
if (cmSystemTools::FileIsFullPath(expDest)) {
|
|
std::string const& installPrefix =
|
|
this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition(
|
|
"CMAKE_INSTALL_PREFIX");
|
|
if (cmHasPrefix(expDest, installPrefix)) {
|
|
auto n = installPrefix.length();
|
|
while (n < expDest.length() && expDest[n] == '/') {
|
|
++n;
|
|
}
|
|
expDest = expDest.substr(n);
|
|
} else {
|
|
this->ReportError(
|
|
cmStrCat("install(PACKAGE_INFO \"", this->GetExportName(),
|
|
"\" ...) specifies DESTINATION \"", expDest,
|
|
"\" which is not a subdirectory of the install prefix."));
|
|
return {};
|
|
}
|
|
}
|
|
|
|
if (expDest.empty()) {
|
|
return this->GetInstallPrefix();
|
|
}
|
|
return cmStrCat(this->GetImportPrefixWithSlash(), expDest);
|
|
}
|
|
|
|
std::string cmExportInstallPackageInfoGenerator::InstallNameDir(
|
|
cmGeneratorTarget const* target, std::string const& config)
|
|
{
|
|
std::string install_name_dir;
|
|
|
|
cmMakefile* mf = target->Target->GetMakefile();
|
|
if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
|
|
install_name_dir =
|
|
target->GetInstallNameDirForInstallTree(config, "@prefix@");
|
|
}
|
|
|
|
return install_name_dir;
|
|
}
|
|
|
|
std::string cmExportInstallPackageInfoGenerator::GetCxxModulesDirectory() const
|
|
{
|
|
// TODO: Implement a not-CMake-specific mechanism for providing module
|
|
// information.
|
|
// return IEGen->GetCxxModuleDirectory();
|
|
return {};
|
|
}
|