install(EXPORT): Install file sets

This commit is contained in:
Kyle Edwards
2021-06-18 14:44:46 -04:00
parent 9b479124cc
commit 2a78d47b16
10 changed files with 249 additions and 5 deletions

View File

@@ -11,12 +11,15 @@
#include <cmext/algorithm>
#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -135,6 +138,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateCompatibleInterfaceProperties(gte, properties);
this->GenerateInterfaceProperties(gte, os, properties);
this->GenerateTargetFileSets(gte, os);
}
// Generate import file content for each configuration.
@@ -356,3 +361,17 @@ std::string cmExportBuildFileGenerator::InstallNameDir(
return install_name_dir;
}
std::string cmExportBuildFileGenerator::GetFileSetDirectories(
cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
{
return cmOutputConverter::EscapeForCMake(
cmJoin(fileSet->GetDirectoryEntries(), ";"));
}
std::string cmExportBuildFileGenerator::GetFileSetFiles(
cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
{
return cmOutputConverter::EscapeForCMake(
cmJoin(fileSet->GetFileEntries(), ";"));
}

View File

@@ -15,9 +15,11 @@
#include "cmStateTypes.h"
class cmExportSet;
class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmLocalGenerator;
class cmTargetExport;
/** \class cmExportBuildFileGenerator
* \brief Generate a file exporting targets from a build tree.
@@ -76,6 +78,11 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override;
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override;
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
cmGlobalGenerator* gg, const std::string& name);

View File

@@ -12,6 +12,7 @@
#include "cmsys/FStream.hxx"
#include "cmComputeLinkInformation.h"
#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -1256,3 +1257,39 @@ bool cmExportFileGenerator::PopulateExportProperties(
}
return true;
}
void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
std::ostream& os,
cmTargetExport* te)
{
auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets();
if (!interfaceFileSets.empty()) {
std::string targetName = cmStrCat(this->Namespace, gte->GetExportName());
os << "if(NOT CMAKE_VERSION VERSION_LESS \"" << DEVEL_CMAKE_VERSION(3, 23)
<< "\")\n"
" target_sources("
<< targetName << "\n";
for (auto const& name : interfaceFileSets) {
auto* fileSet = gte->Target->GetFileSet(name);
if (!fileSet) {
gte->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("File set \"", name,
"\" is listed in interface file sets of ", gte->GetName(),
" but has not been created"));
return;
}
os << " INTERFACE"
<< "\n FILE_SET " << cmOutputConverter::EscapeForCMake(name)
<< "\n TYPE "
<< cmOutputConverter::EscapeForCMake(fileSet->GetType())
<< "\n BASE_DIRS "
<< this->GetFileSetDirectories(gte, fileSet, te) << "\n FILES "
<< this->GetFileSetFiles(gte, fileSet, te) << "\n";
}
os << " )\nendif()\n\n";
}
}

View File

@@ -15,7 +15,9 @@
#include "cmVersion.h"
#include "cmVersionConfig.h"
class cmFileSet;
class cmGeneratorTarget;
class cmTargetExport;
#define STRINGIFY_HELPER(X) #X
#define STRINGIFY(X) STRINGIFY_HELPER(X)
@@ -184,6 +186,16 @@ protected:
ImportPropertyMap& properties,
std::string& errorMessage);
void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
cmTargetExport* te = nullptr);
virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
cmFileSet* fileSet,
cmTargetExport* te) = 0;
virtual std::string GetFileSetFiles(cmGeneratorTarget* gte,
cmFileSet* fileSet,
cmTargetExport* te) = 0;
// The namespace in which the exports are placed in the generated file.
std::string Namespace;

View File

@@ -2,19 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportInstallFileGenerator.h"
#include <algorithm>
#include <memory>
#include <sstream>
#include <utility>
#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -147,6 +151,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateCompatibleInterfaceProperties(gt, properties);
this->GenerateInterfaceProperties(gt, os, properties);
this->GenerateTargetFileSets(gt, os, te);
}
if (require3_1_0) {
@@ -534,3 +540,102 @@ std::string cmExportInstallFileGenerator::InstallNameDir(
return install_name_dir;
}
namespace {
bool EntryIsContextSensitive(
const std::unique_ptr<cmCompiledGeneratorExpression>& cge)
{
return cge->GetHadContextSensitiveCondition();
}
}
std::string cmExportInstallFileGenerator::GetFileSetDirectories(
cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
{
std::vector<std::string> resultVector;
auto configs =
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
cmGeneratorExpression ge;
auto cge = ge.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
for (auto const& config : configs) {
auto dest = cmStrCat("${_IMPORT_PREFIX}/",
cmOutputConverter::EscapeForCMake(
cge->Evaluate(gte->LocalGenerator, config, gte),
cmOutputConverter::WrapQuotes::NoWrap));
if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) {
resultVector.push_back(
cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
} else {
resultVector.push_back(cmStrCat('"', dest, '"'));
break;
}
}
return cmJoin(resultVector, " ");
}
std::string cmExportInstallFileGenerator::GetFileSetFiles(
cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
{
std::vector<std::string> resultVector;
auto configs =
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
auto fileEntries = fileSet->CompileFileEntries();
auto directoryEntries = fileSet->CompileDirectoryEntries();
cmGeneratorExpression destGe;
auto destCge =
destGe.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
for (auto const& config : configs) {
auto directories = fileSet->EvaluateDirectoryEntries(
directoryEntries, gte->LocalGenerator, config, gte);
std::map<std::string, std::vector<std::string>> files;
for (auto const& entry : fileEntries) {
fileSet->EvaluateFileEntry(directories, files, entry,
gte->LocalGenerator, config, gte);
}
auto dest = cmStrCat("${_IMPORT_PREFIX}/",
cmOutputConverter::EscapeForCMake(
destCge->Evaluate(gte->LocalGenerator, config, gte),
cmOutputConverter::WrapQuotes::NoWrap),
'/');
bool const contextSensitive = destCge->GetHadContextSensitiveCondition() ||
std::any_of(directoryEntries.begin(), directoryEntries.end(),
EntryIsContextSensitive) ||
std::any_of(fileEntries.begin(), fileEntries.end(),
EntryIsContextSensitive);
for (auto const& it : files) {
auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/');
for (auto const& filename : it.second) {
auto relFile =
cmStrCat(prefix, cmSystemTools::GetFilenameName(filename));
auto escapedFile =
cmStrCat(dest,
cmOutputConverter::EscapeForCMake(
relFile, cmOutputConverter::WrapQuotes::NoWrap));
if (contextSensitive && configs.size() != 1) {
resultVector.push_back(
cmStrCat("\"$<$<CONFIG:", config, ">:", escapedFile, ">\""));
} else {
resultVector.push_back(cmStrCat('"', escapedFile, '"'));
}
}
}
if (!(contextSensitive && configs.size() != 1)) {
break;
}
}
return cmJoin(resultVector, " ");
}

View File

@@ -14,6 +14,7 @@
#include "cmExportFileGenerator.h"
#include "cmStateTypes.h"
class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmInstallExportGenerator;
@@ -97,6 +98,11 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override;
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override;
cmInstallExportGenerator* IEGen;
// The import file generated for each configuration.

View File

@@ -7,17 +7,22 @@
#include <cm/memory>
#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmValue.h"
class cmTargetExport;
cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
cmGlobalGenerator* gg, const std::vector<std::string>& targets,
cmMakefile* mf, std::set<std::string> const& langs)
@@ -137,3 +142,17 @@ std::string cmExportTryCompileFileGenerator::InstallNameDir(
return install_name_dir;
}
std::string cmExportTryCompileFileGenerator::GetFileSetDirectories(
cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
{
return cmOutputConverter::EscapeForCMake(
cmJoin(fileSet->GetDirectoryEntries(), ";"));
}
std::string cmExportTryCompileFileGenerator::GetFileSetFiles(
cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
{
return cmOutputConverter::EscapeForCMake(
cmJoin(fileSet->GetFileEntries(), ";"));
}

View File

@@ -11,9 +11,11 @@
#include "cmExportFileGenerator.h"
class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
class cmTargetExport;
class cmExportTryCompileFileGenerator : public cmExportFileGenerator
{
@@ -48,6 +50,13 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
std::string GetFileSetDirectories(cmGeneratorTarget* target,
cmFileSet* fileSet,
cmTargetExport* te) override;
std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet,
cmTargetExport* te) override;
private:
std::string FindTargets(const std::string& prop,
const cmGeneratorTarget* tgt,

View File

@@ -729,9 +729,24 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// Track whether this is a namelink-only rule.
bool namelinkOnly = false;
auto addTargetExport = [&]() {
auto addTargetExport = [&]() -> bool {
// Add this install rule to an export if one was specified.
if (!exports.empty()) {
auto interfaceFileSets = target.GetAllInterfaceFileSets();
if (std::any_of(
interfaceFileSets.begin(), interfaceFileSets.end(),
[=](const std::string& name) -> bool {
return !std::any_of(
fileSetArgs.begin(), fileSetArgs.end(),
[=](const cmInstallCommandFileSetArguments& fileSetArg)
-> bool { return fileSetArg.GetFileSet() == name; });
})) {
status.SetError(cmStrCat(
"TARGETS target ", target.GetName(),
" is exported but not all of its file sets are installed"));
return false;
}
auto te = cm::make_unique<cmTargetExport>();
te->TargetName = target.GetName();
te->ArchiveGenerator = archiveGenerator.get();
@@ -741,6 +756,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
te->LibraryGenerator = libraryGenerator.get();
te->RuntimeGenerator = runtimeGenerator.get();
te->ObjectsGenerator = objectGenerator.get();
for (auto const& gen : fileSetGenerators) {
te->FileSetGenerators[gen->GetFileSet()] = gen.get();
}
target.AddInstallIncludeDirectories(
cmMakeRange(includesArgs.GetIncludeDirs()));
te->NamelinkOnly = namelinkOnly;
@@ -748,6 +766,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
->GetExportSets()[exports]
.AddTargetExport(std::move(te));
}
return true;
};
switch (target.GetType()) {
@@ -759,7 +778,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// When in namelink only mode skip all libraries on Windows.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
namelinkOnly = true;
addTargetExport();
if (!addTargetExport()) {
return false;
}
continue;
}
@@ -795,7 +816,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// When in namelink only mode skip frameworks.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
namelinkOnly = true;
addTargetExport();
if (!addTargetExport()) {
return false;
}
continue;
}
@@ -844,7 +867,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// When in namelink only mode skip frameworks.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
namelinkOnly = true;
addTargetExport();
if (!addTargetExport()) {
return false;
}
continue;
}
@@ -1080,7 +1105,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
// Add this install rule to an export if one was specified.
addTargetExport();
if (!addTargetExport()) {
return false;
}
// Keep track of whether we're installing anything in each category
installsArchive = installsArchive || archiveGenerator;

View File

@@ -6,7 +6,9 @@
#include <string>
class cmFileSet;
class cmGeneratorTarget;
class cmInstallFileSetGenerator;
class cmInstallFilesGenerator;
class cmInstallTargetGenerator;
@@ -29,6 +31,7 @@ public:
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
std::map<cmFileSet*, cmInstallFileSetGenerator*> FileSetGenerators;
///@}
bool NamelinkOnly = false;