/* 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 #include #include #include #include #include #include #include "cmFileSet.h" #include "cmGenExContext.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmInstallType.h" #include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMessageType.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" cmInstallFileSetGenerator::cmInstallFileSetGenerator( std::string targetName, std::string fileSetName, cmFileSetDestinations dests, std::string file_permissions, std::vector const& configurations, std::string const& component, MessageLevel message, bool exclude_from_all, bool optional, cmListFileBacktrace backtrace) : cmInstallGenerator("", configurations, component, message, exclude_from_all, false, std::move(backtrace)) , TargetName(std::move(targetName)) , FileSetName(std::move(fileSetName)) , FilePermissions(std::move(file_permissions)) , FileSetDestinations(std::move(dests)) , 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); } auto const& target = *this->Target->Target; this->FileSet = 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; } cmList interfaceFileSetEntries{ target.GetSafeProperty( cmTarget::GetInterfaceFileSetsPropertyName(this->FileSet->GetType())) }; if (std::find(interfaceFileSetEntries.begin(), interfaceFileSetEntries.end(), this->FileSetName) != interfaceFileSetEntries.end()) { if (this->FileSet->GetType() == "HEADERS"_s) { this->Destination = this->FileSetDestinations.Headers; } else { this->Destination = this->FileSetDestinations.CXXModules; } } 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( std::string const& config) const { return cmGeneratorExpression::Evaluate(this->Destination, this->LocalGenerator, config); } 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> cmInstallFileSetGenerator::CalculateFilesPerDir( std::string const& config) const { std::map> result; cm::GenEx::Context context(this->LocalGenerator, config); auto dirCges = this->FileSet->CompileDirectoryEntries(); auto dirs = this->FileSet->EvaluateDirectoryEntries(dirCges, context, this->Target); auto fileCges = this->FileSet->CompileFileEntries(); for (auto const& fileCge : fileCges) { this->FileSet->EvaluateFileEntry(dirs, result, fileCge, context, this->Target); } return result; }