From f644fc8acab04fb7d7dd96648d0f153b12e2936b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 27 Jan 2023 22:41:26 -0500 Subject: cmTarget: introduce a `UsageRequirementProperty` structure This structure will encapsulate the behaviors of usage requirements. There are a number of them now and they all behave very similarly, so try to reduce the code duplication as much as possible. --- Source/cmTarget.cxx | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 1037af7..8388181 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -230,6 +230,50 @@ struct FileSetType void AddFileSet(const std::string& name, cmFileSetVisibility vis, cmListFileBacktrace bt); }; + +struct UsageRequirementProperty +{ + enum class AppendEmpty + { + Yes, + No, + }; + + UsageRequirementProperty(cm::static_string_view name, + AppendEmpty appendEmpty = AppendEmpty::No) + : Name(name) + , AppendBehavior(appendEmpty) + { + } + + void CopyFromDirectory(cmBTStringRange directoryEntries) + { + return cm::append(this->Entries, directoryEntries); + } + + enum class Action + { + Set, + Prepend, + Append, + }; + + template + bool Write(cmTargetInternals const* impl, + cm::optional const& bt, + const std::string& prop, ValueType value, Action action); + template + void WriteDirect(cmTargetInternals const* impl, + cm::optional const& bt, + ValueType value, Action action); + void WriteDirect(BT value, Action action); + std::pair Read(const std::string& prop) const; + + cm::static_string_view const Name; + AppendEmpty const AppendBehavior; + + std::vector> Entries; +}; } class cmTargetInternals @@ -444,6 +488,67 @@ void FileSetType::AddFileSet(const std::string& name, cmFileSetVisibility vis, } } +template +bool UsageRequirementProperty::Write( + cmTargetInternals const* impl, cm::optional const& bt, + const std::string& prop, ValueType value, Action action) +{ + if (prop == this->Name) { + this->WriteDirect(impl, bt, value, action); + return true; + } + return false; +} + +template +void UsageRequirementProperty::WriteDirect( + cmTargetInternals const* impl, cm::optional const& bt, + ValueType value, Action action) +{ + if (action == Action::Set) { + this->Entries.clear(); + } + if (value) { + cmListFileBacktrace lfbt = impl->GetBacktrace(bt); + if (action == Action::Prepend) { + this->Entries.emplace(this->Entries.begin(), value, lfbt); + } else if (action == Action::Set || cmNonempty(value) || + this->AppendBehavior == AppendEmpty::Yes) { + this->Entries.emplace_back(value, lfbt); + } + } +} + +void UsageRequirementProperty::WriteDirect(BT value, + Action action) +{ + if (action == Action::Set) { + this->Entries.clear(); + } + if (action == Action::Prepend) { + this->Entries.emplace(this->Entries.begin(), std::move(value)); + } else { + this->Entries.emplace_back(std::move(value)); + } +} + +std::pair UsageRequirementProperty::Read( + const std::string& prop) const +{ + bool did_read = false; + cmValue value = nullptr; + if (prop == this->Name) { + if (!this->Entries.empty()) { + // Storage to back the returned `cmValue`. + static std::string output; + output = cmJoin(this->Entries, ";"); + value = cmValue(output); + } + did_read = true; + } + return { did_read, value }; +} + namespace { #define SETUP_COMMON_LANGUAGE_PROPERTIES(lang) \ initProp(#lang "_COMPILER_LAUNCHER"); \ -- cgit v0.12