mirror of
https://github.com/Kitware/CMake.git
synced 2026-08-09 17:18:18 +00:00
Add `-Winstall-absolute-destination` diagnostic to warn or error when an install command has an absolute destination. This allow projects to enforce the best practice of not allowing absolute install DESTINATIONS.
152 lines
4.9 KiB
C++
152 lines
4.9 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file LICENSE.rst or https://cmake.org/licensing for details. */
|
|
#include "cmInstallFileSetGenerator.h"
|
|
|
|
#include <algorithm>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <cm/string_view>
|
|
|
|
#include "cmFileSetMetadata.h"
|
|
#include "cmGenExContext.h"
|
|
#include "cmGeneratorExpression.h"
|
|
#include "cmGeneratorFileSet.h"
|
|
#include "cmGeneratorTarget.h"
|
|
#include "cmGlobalGenerator.h"
|
|
#include "cmInstallDirs.h"
|
|
#include "cmInstallType.h"
|
|
#include "cmList.h"
|
|
#include "cmListFileCache.h"
|
|
#include "cmLocalGenerator.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmMessageType.h"
|
|
#include "cmStringAlgorithms.h"
|
|
#include "cmTarget.h"
|
|
|
|
cmInstallFileSetGenerator::cmInstallFileSetGenerator(
|
|
std::string targetName, std::string fileSetName, std::string destination,
|
|
std::string file_permissions, std::vector<std::string> const& configurations,
|
|
std::string const& component, MessageLevel message, bool exclude_from_all,
|
|
bool optional, cmListFileBacktrace backtrace)
|
|
: cmInstallGenerator(std::move(destination), configurations, component,
|
|
message, exclude_from_all, false, std::move(backtrace))
|
|
, TargetName(std::move(targetName))
|
|
, FileSetName(std::move(fileSetName))
|
|
, FilePermissions(std::move(file_permissions))
|
|
, Optional(optional)
|
|
{
|
|
this->ActionsPerConfig = true;
|
|
}
|
|
|
|
cmInstallFileSetGenerator::~cmInstallFileSetGenerator() = default;
|
|
|
|
bool cmInstallFileSetGenerator::Compute(cmLocalGenerator* lg)
|
|
{
|
|
this->LocalGenerator = lg;
|
|
|
|
// Lookup this target in the current directory.
|
|
this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
|
|
if (!this->Target) {
|
|
// If no local target has been found, find it in the global scope.
|
|
this->Target =
|
|
lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
|
|
}
|
|
|
|
this->FileSet = this->Target->GetFileSet(this->FileSetName);
|
|
|
|
if (!this->FileSet) {
|
|
// No file set of the given name was ever provided for this target, nothing
|
|
// for this generator to do
|
|
return true;
|
|
}
|
|
|
|
auto const& target = *this->Target->Target;
|
|
cmList interfaceFileSetEntries{ target.GetSafeProperty(
|
|
target.GetInterfaceFileSetsPropertyName(this->FileSet->GetType())) };
|
|
|
|
if (std::find(interfaceFileSetEntries.begin(), interfaceFileSetEntries.end(),
|
|
this->FileSetName) != interfaceFileSetEntries.end()) {
|
|
if (this->FileSet->GetType() == cm::FileSetMetadata::HEADERS) {
|
|
if (this->Destination.empty()) {
|
|
this->Destination =
|
|
cm::InstallDirs::GetIncludeDirectory(lg->GetMakefile());
|
|
}
|
|
}
|
|
} else {
|
|
// File set of the given name was provided but it's private, so give up
|
|
this->FileSet = nullptr;
|
|
return true;
|
|
}
|
|
|
|
if (this->Destination.empty()) {
|
|
lg->IssueMessage(MessageType::FATAL_ERROR,
|
|
cmStrCat("File set \"", this->FileSetName,
|
|
"\" installed by target \"", this->TargetName,
|
|
"\" has no destination."));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::string cmInstallFileSetGenerator::GetDestination() const
|
|
{
|
|
cmInstallGenerator::CheckAbsoluteDestination(
|
|
this->Destination, this->LocalGenerator, this->Backtrace);
|
|
return this->Destination;
|
|
}
|
|
|
|
std::string cmInstallFileSetGenerator::GetDestination(
|
|
std::string const& config) const
|
|
{
|
|
return this->GetDestination(this->Target, config).UnescapedDestination;
|
|
}
|
|
|
|
cmInstallFileSetGenerator::DestinationContext
|
|
cmInstallFileSetGenerator::GetDestination(cmGeneratorTarget* gte,
|
|
std::string const& config) const
|
|
{
|
|
cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance());
|
|
std::unique_ptr<cmCompiledGeneratorExpression> cge =
|
|
ge.Parse(this->Destination);
|
|
|
|
std::string const dest = cge->Evaluate(gte->LocalGenerator, config, gte);
|
|
cmInstallGenerator::CheckAbsoluteDestination(dest, gte->LocalGenerator,
|
|
this->Backtrace);
|
|
|
|
return { dest, cge->GetHadContextSensitiveCondition() };
|
|
}
|
|
|
|
void cmInstallFileSetGenerator::GenerateScriptForConfig(
|
|
std::ostream& os, std::string const& config, Indent indent)
|
|
{
|
|
|
|
if (!this->FileSet) {
|
|
return;
|
|
}
|
|
|
|
for (auto const& dirEntry : this->CalculateFilesPerDir(config)) {
|
|
std::string destSub;
|
|
if (!dirEntry.first.empty()) {
|
|
destSub = cmStrCat('/', dirEntry.first);
|
|
}
|
|
this->AddInstallRule(os, cmStrCat(this->GetDestination(config), destSub),
|
|
cmInstallType_FILES, dirEntry.second,
|
|
this->GetOptional(), this->FilePermissions.c_str(),
|
|
nullptr, nullptr, nullptr, indent);
|
|
}
|
|
}
|
|
|
|
std::map<std::string, std::vector<std::string>>
|
|
cmInstallFileSetGenerator::CalculateFilesPerDir(
|
|
std::string const& config) const
|
|
{
|
|
cm::GenEx::Context context(this->LocalGenerator, config);
|
|
|
|
return this->FileSet->GetFiles(context, this->Target).first;
|
|
}
|