mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
CPS: Implement exporting of file sets
Add (partial) file set export to CPS. For now, only headers ("includes")
are supported, as that is the only overlap with the specification.
(Source file sets are not supported by CPS at this time, and the hope is
that C++ modules will never be supported, as that information should
already be available via the `cpp_module_metadata` information.) CPS
also supports "embeds", but CMake doesn't (yet).
This also introduces our first official use of CPS extensions, used to
record the CMake file set name.
This commit is contained in:
@@ -14,7 +14,11 @@
|
||||
|
||||
#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 "cmStateTypes.h"
|
||||
@@ -84,6 +88,7 @@ bool cmExportBuildPackageInfoGenerator::GenerateMainFile(std::ostream& os)
|
||||
|
||||
// Set configuration-agnostic properties for component.
|
||||
this->GenerateInterfaceProperties(*component, target, properties);
|
||||
this->GenerateTargetFileSets(*component, target);
|
||||
}
|
||||
|
||||
this->GeneratePackageRequires(root);
|
||||
@@ -125,6 +130,35 @@ void cmExportBuildPackageInfoGenerator::GenerateInterfacePropertiesConfig(
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -48,4 +48,11 @@ protected:
|
||||
std::string const& config);
|
||||
|
||||
std::string GetCxxModulesDirectory() const override;
|
||||
|
||||
using cmExportPackageInfoGenerator::GenerateTargetFileSets;
|
||||
void GenerateTargetFileSets(Json::Value& fileSets,
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorFileSet const* fileSet,
|
||||
cmTargetExport const* targetExport,
|
||||
std::string const& type) const override;
|
||||
};
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
#include <cm3p/json/value.h>
|
||||
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmDiagnostics.h"
|
||||
#include "cmExportSet.h"
|
||||
#include "cmFileSetMetadata.h"
|
||||
#include "cmGenExContext.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
@@ -115,6 +117,7 @@ bool cmExportInstallPackageInfoGenerator::GenerateMainFile(std::ostream& os)
|
||||
if (!this->GenerateFileSetProperties(*component, gt, te, packagePath)) {
|
||||
return false;
|
||||
}
|
||||
this->GenerateTargetFileSets(*component, gt, te);
|
||||
}
|
||||
|
||||
this->GeneratePackageRequires(root);
|
||||
@@ -289,3 +292,43 @@ bool cmExportInstallPackageInfoGenerator::GenerateFileSetProperties(
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmExportInstallPackageInfoGenerator::GenerateTargetFileSets(
|
||||
Json::Value& fileSets, cmGeneratorTarget const* target,
|
||||
cmGeneratorFileSet const* fileSet, cmTargetExport const* targetExport,
|
||||
std::string const& type) const
|
||||
{
|
||||
cm::optional<std::string> dest =
|
||||
this->GetFileSetDirectory(target, targetExport, fileSet);
|
||||
if (!dest) {
|
||||
this->IssueDiagnostic(
|
||||
cmDiagnostics::CMD_AUTHOR,
|
||||
cmStrCat("The \""_s, target->GetName(),
|
||||
"\" target's interface file set \""_s, fileSet->GetName(),
|
||||
"\" of type \""_s, fileSet->GetType(),
|
||||
"\" has a context-sensitive destination, which is not "
|
||||
"supported. The file set will not be exported."_s));
|
||||
return;
|
||||
}
|
||||
|
||||
cm::GenEx::Context context{ target->LocalGenerator, {} };
|
||||
|
||||
std::vector<std::string> files;
|
||||
auto eval = [&files](std::string&& /*baseDir*/, std::string&& relPath,
|
||||
std::string&& /*file*/) {
|
||||
files.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;
|
||||
}
|
||||
|
||||
this->GenerateTargetFileSet(fileSets, fileSet, type, *dest, files);
|
||||
}
|
||||
|
||||
@@ -80,4 +80,11 @@ protected:
|
||||
cmTargetExport const* te,
|
||||
std::string const& packagePath,
|
||||
cm::optional<std::string> config = {});
|
||||
|
||||
using cmExportPackageInfoGenerator::GenerateTargetFileSets;
|
||||
void GenerateTargetFileSets(Json::Value& fileSets,
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorFileSet const* fileSet,
|
||||
cmTargetExport const* targetExport,
|
||||
std::string const& type) const override;
|
||||
};
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "cmExportSet.h"
|
||||
#include "cmFindPackageStack.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorFileSets.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmList.h"
|
||||
#include "cmMakefile.h"
|
||||
@@ -296,6 +298,54 @@ bool cmExportPackageInfoGenerator::GenerateInterfaceProperties(
|
||||
return result;
|
||||
}
|
||||
|
||||
void cmExportPackageInfoGenerator::GenerateTargetFileSets(
|
||||
Json::Value& component, cmGeneratorTarget const* target,
|
||||
cmTargetExport const* targetExport) const
|
||||
{
|
||||
cmGeneratorFileSets const* gfs = target->GetGeneratorFileSets();
|
||||
|
||||
for (auto const& type : gfs->GetInterfaceFileSetTypes()) {
|
||||
// Do we support this file set type?
|
||||
std::string fsType;
|
||||
if (type == "HEADERS") {
|
||||
fsType = "includes";
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Generate CPS file set(s) for each CMake file set
|
||||
Json::Value fileSets;
|
||||
for (cmGeneratorFileSet const* fileSet : gfs->GetInterfaceFileSets(type)) {
|
||||
this->GenerateTargetFileSets(fileSets, target, fileSet, targetExport,
|
||||
fsType);
|
||||
}
|
||||
|
||||
if (!fileSets.empty()) {
|
||||
component["file_sets"] = fileSets;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmExportPackageInfoGenerator::GenerateTargetFileSet(
|
||||
Json::Value& fileSets, cmGeneratorFileSet const* fileSet,
|
||||
std::string const& type, std::string const& root,
|
||||
std::vector<std::string> const& files)
|
||||
{
|
||||
Json::Value fileSetOut;
|
||||
fileSetOut["type"] = type;
|
||||
fileSetOut["root"] = root;
|
||||
|
||||
Json::Value filesOut;
|
||||
for (auto const& f : files) {
|
||||
filesOut.append(f);
|
||||
}
|
||||
fileSetOut["files"] = filesOut;
|
||||
|
||||
fileSetOut["extensions"]["cmake"]["name@v1"] = fileSet->GetName();
|
||||
|
||||
fileSets.append(fileSetOut);
|
||||
}
|
||||
|
||||
bool cmExportPackageInfoGenerator::NoteLinkedTarget(
|
||||
cmGeneratorTarget const* target, std::string const& linkedName,
|
||||
cmGeneratorTarget const* linkedTarget)
|
||||
|
||||
@@ -19,8 +19,10 @@ namespace Json {
|
||||
class Value;
|
||||
}
|
||||
|
||||
class cmGeneratorFileSet;
|
||||
class cmGeneratorTarget;
|
||||
class cmPackageInfoArguments;
|
||||
class cmTargetExport;
|
||||
|
||||
/** \class cmExportPackageInfoGenerator
|
||||
* \brief Generate Common Package Specification package information files
|
||||
@@ -66,6 +68,20 @@ protected:
|
||||
Json::Value GenerateInterfaceConfigProperties(
|
||||
std::string const& suffix, ImportPropertyMap const& properties) const;
|
||||
|
||||
void GenerateTargetFileSets(
|
||||
Json::Value& component, cmGeneratorTarget const* target,
|
||||
cmTargetExport const* targetExport = nullptr) const;
|
||||
virtual void GenerateTargetFileSets(Json::Value& fileSets,
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorFileSet const* fileSet,
|
||||
cmTargetExport const* targetExport,
|
||||
std::string const& type) const = 0;
|
||||
static void GenerateTargetFileSet(Json::Value& fileSets,
|
||||
cmGeneratorFileSet const* fileSet,
|
||||
std::string const& type,
|
||||
std::string const& root,
|
||||
std::vector<std::string> const& files);
|
||||
|
||||
cm::string_view GetImportPrefixWithSlash() const override;
|
||||
|
||||
std::string GetCxxModuleFile(std::string const& /*name*/) const override
|
||||
|
||||
@@ -8,3 +8,22 @@ string(JSON component GET "${content}" "components" "foo")
|
||||
|
||||
expect_array("${component}" 1 "includes")
|
||||
expect_value("${component}" "${CMAKE_CURRENT_LIST_DIR}/foo" "includes" 0)
|
||||
|
||||
expect_array("${component}" 2 "file_sets")
|
||||
|
||||
expect_value("${component}" "includes" "file_sets" 0 "type")
|
||||
expect_value("${component}" "${CMAKE_CURRENT_LIST_DIR}/foo"
|
||||
"file_sets" 0 "root")
|
||||
expect_array("${component}" 2 "file_sets" 0 "files")
|
||||
expect_value("${component}" "header1.h" "file_sets" 0 "files" 0)
|
||||
expect_value("${component}" "header2.h" "file_sets" 0 "files" 1)
|
||||
expect_value("${component}" "no_genex"
|
||||
"file_sets" 0 "extensions" "cmake" "name@v1")
|
||||
|
||||
expect_value("${component}" "includes" "file_sets" 1 "type")
|
||||
expect_value("${component}" "${CMAKE_CURRENT_LIST_DIR}/foo"
|
||||
"file_sets" 1 "root")
|
||||
expect_array("${component}" 1 "file_sets" 1 "files")
|
||||
expect_value("${component}" "header3.h" "file_sets" 1 "files" 0)
|
||||
expect_value("${component}" "genex"
|
||||
"file_sets" 1 "extensions" "cmake" "name@v1")
|
||||
|
||||
@@ -8,11 +8,16 @@ target_sources(foo
|
||||
FILE_SET no_genex
|
||||
TYPE HEADERS
|
||||
BASE_DIRS ${CMAKE_CURRENT_LIST_DIR}/foo
|
||||
FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/foo/header1.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/foo/header2.h
|
||||
|
||||
INTERFACE
|
||||
FILE_SET genex
|
||||
TYPE HEADERS
|
||||
BASE_DIRS ${CMAKE_CURRENT_LIST_DIR}/foo
|
||||
FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/foo/header3.h
|
||||
)
|
||||
|
||||
install(
|
||||
|
||||
@@ -9,6 +9,24 @@ string(JSON component GET "${content}" "components" "foo")
|
||||
expect_array("${component}" 1 "includes")
|
||||
expect_value("${component}" "@prefix@/no_genex" "includes" 0)
|
||||
|
||||
expect_array("${component}" 2 "file_sets")
|
||||
|
||||
expect_value("${component}" "includes" "file_sets" 0 "type")
|
||||
expect_value("${component}" "@prefix@/no_genex" "file_sets" 0 "root")
|
||||
expect_array("${component}" 2 "file_sets" 0 "files")
|
||||
expect_value("${component}" "header1.h" "file_sets" 0 "files" 0)
|
||||
expect_value("${component}" "header2.h" "file_sets" 0 "files" 1)
|
||||
expect_value("${component}" "no_genex"
|
||||
"file_sets" 0 "extensions" "cmake" "name@v1")
|
||||
|
||||
expect_value("${component}" "includes" "file_sets" 1 "type")
|
||||
expect_value("${component}" "@prefix@/no_genex" "file_sets" 1 "root")
|
||||
expect_array("${component}" 2 "file_sets" 1 "files")
|
||||
expect_value("${component}" "header1.h" "file_sets" 1 "files" 0)
|
||||
expect_value("${component}" "header2.h" "file_sets" 1 "files" 1)
|
||||
expect_value("${component}" "no_genex_dup"
|
||||
"file_sets" 1 "extensions" "cmake" "name@v1")
|
||||
|
||||
file(GLOB configs "${out_dir}/foo@*.cps")
|
||||
list(LENGTH configs configs_len)
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
CMake Warning \(author\) at FileSetHeaders\.cmake:[0-9]+ \(install\):
|
||||
The "foo" target's interface file set "genex" of type "HEADERS" has a
|
||||
context-sensitive destination, which is not supported\. The file set will
|
||||
not be exported\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:3 \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.
|
||||
|
||||
CMake Warning \(author\) at FileSetHeaders\.cmake:[0-9]+ \(install\):
|
||||
The "foo" target's interface file set "genex_dup" of type "HEADERS" has a
|
||||
context-sensitive destination, which is not supported\. The file set will
|
||||
not be exported\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:3 \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.
|
||||
@@ -4,10 +4,18 @@ target_sources(foo
|
||||
INTERFACE
|
||||
FILE_SET no_genex
|
||||
TYPE HEADERS
|
||||
BASE_DIRS foo
|
||||
FILES
|
||||
foo/header1.h
|
||||
foo/header2.h
|
||||
|
||||
INTERFACE
|
||||
FILE_SET no_genex_dup
|
||||
TYPE HEADERS
|
||||
BASE_DIRS foo
|
||||
FILES
|
||||
foo/header1.h
|
||||
foo/header2.h
|
||||
|
||||
INTERFACE
|
||||
FILE_SET genex
|
||||
|
||||
Reference in New Issue
Block a user