summaryrefslogtreecommitdiff
path: root/Source/cmTarget.cxx
diff options
context:
space:
mode:
authorKyle Edwards <kyle.edwards@kitware.com>2021-06-16 17:09:59 -0400
committerKyle Edwards <kyle.edwards@kitware.com>2021-10-27 15:17:23 -0400
commitf2a44a8afabe6d0d87f1b5d4acf31b2049a021fd (patch)
treef1630cf49f0372ad7a8d1e7e14ee2d38076cb537 /Source/cmTarget.cxx
parent447fbf061a5f27abbad59a9fc943de4f8351f9fe (diff)
downloadcmake-f2a44a8afabe6d0d87f1b5d4acf31b2049a021fd.tar.gz
cmTarget: Add cmFileSet and associated properties
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r--Source/cmTarget.cxx321
1 files changed, 320 insertions, 1 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 97d60cf030..4f0dc6071c 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -14,11 +14,13 @@
#include <cm/memory>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -200,8 +202,11 @@ public:
std::vector<BT<std::string>> LinkOptionsEntries;
std::vector<BT<std::string>> LinkDirectoriesEntries;
std::vector<BT<std::string>> LinkImplementationPropertyEntries;
+ std::vector<BT<std::string>> HeaderSetsEntries;
+ std::vector<BT<std::string>> InterfaceHeaderSetsEntries;
std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
TLLCommands;
+ std::map<std::string, cmFileSet> FileSets;
cmListFileBacktrace Backtrace;
bool CheckImportedLibName(std::string const& prop,
@@ -1110,6 +1115,16 @@ cmBTStringRange cmTarget::GetLinkImplementationEntries() const
return cmMakeRange(this->impl->LinkImplementationPropertyEntries);
}
+cmBTStringRange cmTarget::GetHeaderSetsEntries() const
+{
+ return cmMakeRange(this->impl->HeaderSetsEntries);
+}
+
+cmBTStringRange cmTarget::GetInterfaceHeaderSetsEntries() const
+{
+ return cmMakeRange(this->impl->InterfaceHeaderSetsEntries);
+}
+
namespace {
#define MAKE_PROP(PROP) const std::string prop##PROP = #PROP
MAKE_PROP(C_STANDARD);
@@ -1139,6 +1154,10 @@ MAKE_PROP(BINARY_DIR);
MAKE_PROP(SOURCE_DIR);
MAKE_PROP(FALSE);
MAKE_PROP(TRUE);
+MAKE_PROP(HEADER_DIRS);
+MAKE_PROP(HEADER_SET);
+MAKE_PROP(HEADER_SETS);
+MAKE_PROP(INTERFACE_HEADER_SETS);
#undef MAKE_PROP
}
@@ -1158,6 +1177,21 @@ std::string ConvertToString<cmValue>(cmValue value)
{
return std::string(*value);
}
+
+template <typename ValueType>
+bool StringIsEmpty(ValueType value);
+
+template <>
+bool StringIsEmpty<const char*>(const char* value)
+{
+ return cmValue::IsEmpty(value);
+}
+
+template <>
+bool StringIsEmpty<cmValue>(cmValue value)
+{
+ return value.IsEmpty();
+}
}
template <typename ValueType>
@@ -1321,6 +1355,104 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value)
} else {
this->impl->LanguageStandardProperties.erase(prop);
}
+ } else if (prop == propHEADER_DIRS) {
+ auto* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The default header set has not yet been created.");
+ return;
+ }
+ fileSet->ClearDirectoryEntries();
+ if (!StringIsEmpty(value)) {
+ fileSet->AddDirectoryEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ }
+ } else if (prop == propHEADER_SET) {
+ auto* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The default header set has not yet been created.");
+ return;
+ }
+ fileSet->ClearFileEntries();
+ if (!StringIsEmpty(value)) {
+ fileSet->AddFileEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ }
+ } else if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) {
+ auto fileSetName = prop.substr(cmStrLen("HEADER_DIRS_"));
+ if (fileSetName.empty()) {
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "Header set name cannot be empty.");
+ return;
+ }
+ auto* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", fileSetName,
+ "\" has not yet been created."));
+ return;
+ }
+ fileSet->ClearDirectoryEntries();
+ if (!StringIsEmpty(value)) {
+ fileSet->AddDirectoryEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ }
+ } else if (cmHasLiteralPrefix(prop, "HEADER_SET_")) {
+ auto fileSetName = prop.substr(cmStrLen("HEADER_SET_"));
+ if (fileSetName.empty()) {
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "Header set name cannot be empty.");
+ return;
+ }
+ auto* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", fileSetName,
+ "\" has not yet been created."));
+ return;
+ }
+ fileSet->ClearFileEntries();
+ if (!StringIsEmpty(value)) {
+ fileSet->AddFileEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ }
+ } else if (prop == propHEADER_SETS) {
+ if (value) {
+ for (auto const& name : cmExpandedList(value)) {
+ if (!this->GetFileSet(name)) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", name, "\" has not yet been created."));
+ return;
+ }
+ }
+ }
+ this->impl->HeaderSetsEntries.clear();
+ if (!StringIsEmpty(value)) {
+ this->impl->HeaderSetsEntries.emplace_back(
+ value, this->impl->Makefile->GetBacktrace());
+ }
+ } else if (prop == propINTERFACE_HEADER_SETS) {
+ if (value) {
+ for (auto const& name : cmExpandedList(value)) {
+ if (!this->GetFileSet(name)) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", name, "\" has not yet been created."));
+ return;
+ }
+ }
+ }
+ this->impl->InterfaceHeaderSetsEntries.clear();
+ if (!StringIsEmpty(value)) {
+ this->impl->InterfaceHeaderSetsEntries.emplace_back(
+ value, this->impl->Makefile->GetBacktrace());
+ }
} else {
this->impl->Properties.SetProperty(prop, value);
}
@@ -1415,6 +1547,82 @@ void cmTarget::AppendProperty(const std::string& prop,
prop == "OBJC_STANDARD" || prop == "OBJCXX_STANDARD") {
this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR, prop + " property may not be appended.");
+ } else if (prop == "HEADER_DIRS") {
+ auto* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The default header set has not yet been created.");
+ return;
+ }
+ fileSet->AddDirectoryEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ } else if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) {
+ auto fileSetName = prop.substr(cmStrLen("HEADER_DIRS_"));
+ if (fileSetName.empty()) {
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "Header set name cannot be empty.");
+ return;
+ }
+ auto* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", fileSetName,
+ "\" has not yet been created."));
+ return;
+ }
+ fileSet->AddDirectoryEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ } else if (prop == "HEADER_SET") {
+ auto* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The default header set has not yet been created.");
+ return;
+ }
+ fileSet->AddFileEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ } else if (cmHasLiteralPrefix(prop, "HEADER_SET_")) {
+ auto fileSetName = prop.substr(cmStrLen("HEADER_SET_"));
+ if (fileSetName.empty()) {
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "Header set name cannot be empty.");
+ return;
+ }
+ auto* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", fileSetName,
+ "\" has not yet been created."));
+ return;
+ }
+ fileSet->AddFileEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ } else if (prop == "HEADER_SETS") {
+ for (auto const& name : cmExpandedList(value)) {
+ if (!this->GetFileSet(name)) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", name, "\" has not yet been created."));
+ return;
+ }
+ }
+ this->impl->HeaderSetsEntries.emplace_back(
+ value, this->impl->Makefile->GetBacktrace());
+ } else if (prop == "INTERFACE_HEADER_SETS") {
+ for (auto const& name : cmExpandedList(value)) {
+ if (!this->GetFileSet(name)) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", name, "\" has not yet been created."));
+ return;
+ }
+ }
+ this->impl->InterfaceHeaderSetsEntries.emplace_back(
+ value, this->impl->Makefile->GetBacktrace());
} else {
this->impl->Properties.AppendProperty(prop, value, asString);
}
@@ -1633,7 +1841,11 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
propNAME,
propBINARY_DIR,
propSOURCE_DIR,
- propSOURCES
+ propSOURCES,
+ propHEADER_DIRS,
+ propHEADER_SET,
+ propHEADER_SETS,
+ propINTERFACE_HEADER_SETS,
};
if (specialProps.count(prop)) {
if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
@@ -1759,6 +1971,60 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
.GetDirectory()
.GetCurrentSource());
}
+ if (prop == propHEADER_DIRS) {
+ auto const* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ return nullptr;
+ }
+ static std::string output;
+ output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s);
+ return cmValue(output);
+ }
+ if (prop == propHEADER_SET) {
+ auto const* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ return nullptr;
+ }
+ static std::string output;
+ output = cmJoin(fileSet->GetFileEntries(), ";"_s);
+ return cmValue(output);
+ }
+ if (prop == propHEADER_SETS) {
+ static std::string output;
+ output = cmJoin(this->impl->HeaderSetsEntries, ";"_s);
+ return cmValue(output);
+ }
+ if (prop == propINTERFACE_HEADER_SETS) {
+ static std::string output;
+ output = cmJoin(this->impl->InterfaceHeaderSetsEntries, ";"_s);
+ return cmValue(output);
+ }
+ }
+ if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) {
+ std::string fileSetName = prop.substr(cmStrLen("HEADER_DIRS_"));
+ if (fileSetName.empty()) {
+ return nullptr;
+ }
+ auto const* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ return nullptr;
+ }
+ static std::string output;
+ output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s);
+ return cmValue(output);
+ }
+ if (cmHasLiteralPrefix(prop, "HEADER_SET_")) {
+ std::string fileSetName = prop.substr(cmStrLen("HEADER_SET_"));
+ if (fileSetName.empty()) {
+ return nullptr;
+ }
+ auto const* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ return nullptr;
+ }
+ static std::string output;
+ output = cmJoin(fileSet->GetFileEntries(), ";"_s);
+ return cmValue(output);
}
cmValue retVal = this->impl->Properties.GetPropertyValue(prop);
@@ -2015,6 +2281,59 @@ std::string cmTarget::ImportedGetFullPath(
return result;
}
+const cmFileSet* cmTarget::GetFileSet(const std::string& name) const
+{
+ auto it = this->impl->FileSets.find(name);
+ return it == this->impl->FileSets.end() ? nullptr : &it->second;
+}
+
+cmFileSet* cmTarget::GetFileSet(const std::string& name)
+{
+ auto it = this->impl->FileSets.find(name);
+ return it == this->impl->FileSets.end() ? nullptr : &it->second;
+}
+
+std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet(
+ const std::string& name, const std::string& type)
+{
+ auto result =
+ this->impl->FileSets.emplace(std::make_pair(name, cmFileSet(name, type)));
+ return std::make_pair(&result.first->second, result.second);
+}
+
+std::string cmTarget::GetFileSetsPropertyName(const std::string& type)
+{
+ if (type == "HEADERS") {
+ return "HEADER_SETS";
+ }
+ return "";
+}
+
+std::string cmTarget::GetInterfaceFileSetsPropertyName(const std::string& type)
+{
+ if (type == "HEADERS") {
+ return "INTERFACE_HEADER_SETS";
+ }
+ return "";
+}
+
+std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const
+{
+ std::vector<std::string> result;
+ auto inserter = std::back_inserter(result);
+
+ auto appendEntries = [=](const std::vector<BT<std::string>>& entries) {
+ for (auto const& entry : entries) {
+ auto expanded = cmExpandedList(entry.Value);
+ std::copy(expanded.begin(), expanded.end(), inserter);
+ }
+ };
+
+ appendEntries(this->impl->InterfaceHeaderSetsEntries);
+
+ return result;
+}
+
bool cmTargetInternals::CheckImportedLibName(std::string const& prop,
std::string const& value) const
{