blob: 72518109496b00e2f4754e296d610595e55fbf2a [file] [log] [blame] [edit]
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmSourceGroup.h"
#include <utility>
#include <cm/memory>
#include "cmGeneratorExpression.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
class cmSourceGroupInternals
{
public:
SourceGroupVector GroupChildren;
};
cmSourceGroup::cmSourceGroup(std::string name, char const* regex,
char const* parentName)
: Name(std::move(name))
{
this->Internal = cm::make_unique<cmSourceGroupInternals>();
this->SetGroupRegex(regex);
if (parentName) {
this->FullName = cmStrCat(parentName, '\\');
}
this->FullName += this->Name;
}
cmSourceGroup::~cmSourceGroup() = default;
void cmSourceGroup::SetGroupRegex(char const* regex)
{
if (regex) {
this->GroupRegex.compile(regex);
} else {
this->GroupRegex.compile("^$");
}
}
void cmSourceGroup::ResolveGenex(cmLocalGenerator* lg,
std::string const& config)
{
std::set<std::string> files;
for (std::string const& file : this->GroupFiles) {
files.emplace(cmGeneratorExpression::Evaluate(file, lg, config));
}
this->GroupFiles = std::move(files);
if (!this->Internal) {
return;
}
for (auto const& group : this->Internal->GroupChildren) {
group->ResolveGenex(lg, config);
}
}
void cmSourceGroup::AddGroupFile(std::string const& name)
{
this->GroupFiles.insert(name);
}
std::string const& cmSourceGroup::GetName() const
{
return this->Name;
}
std::string const& cmSourceGroup::GetFullName() const
{
return this->FullName;
}
bool cmSourceGroup::MatchesRegex(std::string const& name) const
{
cmsys::RegularExpressionMatch match;
return this->GroupRegex.find(name.c_str(), match);
}
bool cmSourceGroup::MatchesFiles(std::string const& name) const
{
return this->GroupFiles.find(name) != this->GroupFiles.cend();
}
void cmSourceGroup::AssignSource(cmSourceFile const* sf)
{
this->SourceFiles.push_back(sf);
}
std::set<std::string> const& cmSourceGroup::GetGroupFiles() const
{
return this->GroupFiles;
}
std::vector<cmSourceFile const*> const& cmSourceGroup::GetSourceFiles() const
{
return this->SourceFiles;
}
void cmSourceGroup::AddChild(std::unique_ptr<cmSourceGroup> child)
{
this->Internal->GroupChildren.push_back(std::move(child));
}
cmSourceGroup* cmSourceGroup::LookupChild(std::string const& name) const
{
for (auto& group : this->Internal->GroupChildren) {
// look if descendant is the one we're looking for
if (group->GetName() == name) {
return group.get(); // if so return it
}
}
// if no child with this name was found return NULL
return nullptr;
}
cmSourceGroup* cmSourceGroup::MatchChildrenFiles(std::string const& name)
{
if (this->MatchesFiles(name)) {
return this;
}
for (auto& group : this->Internal->GroupChildren) {
cmSourceGroup* result = group->MatchChildrenFiles(name);
if (result) {
return result;
}
}
return nullptr;
}
cmSourceGroup const* cmSourceGroup::MatchChildrenFiles(
std::string const& name) const
{
if (this->MatchesFiles(name)) {
return this;
}
for (auto const& group : this->Internal->GroupChildren) {
cmSourceGroup const* result = group->MatchChildrenFiles(name);
if (result) {
return result;
}
}
return nullptr;
}
cmSourceGroup* cmSourceGroup::MatchChildrenRegex(std::string const& name) const
{
for (auto& group : this->Internal->GroupChildren) {
cmSourceGroup* result = group->MatchChildrenRegex(name);
if (result) {
return result;
}
}
if (this->MatchesRegex(name)) {
return const_cast<cmSourceGroup*>(this);
}
return nullptr;
}
SourceGroupVector const& cmSourceGroup::GetGroupChildren() const
{
return this->Internal->GroupChildren;
}
/**
* Find a source group whose regular expression matches the filename
* part of the given source name. Search backward through the list of
* source groups, and take the first matching group found. This way
* non-inherited SOURCE_GROUP commands will have precedence over
* inherited ones.
*/
cmSourceGroup* cmSourceGroup::FindSourceGroup(std::string const& source,
SourceGroupVector const& groups)
{
// First search for a group that lists the file explicitly.
for (auto sg = groups.rbegin(); sg != groups.rend(); ++sg) {
cmSourceGroup* result = (*sg)->MatchChildrenFiles(source);
if (result) {
return result;
}
}
// Now search for a group whose regex matches the file.
for (auto sg = groups.rbegin(); sg != groups.rend(); ++sg) {
cmSourceGroup* result = (*sg)->MatchChildrenRegex(source);
if (result) {
return result;
}
}
// Shouldn't get here, but just in case, return the default group.
return groups.data()->get();
}