mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
Since commit de2afc5d53 (cmMakeFile: Remove source groups argument from
`FindSourceGroup`, 2025-11-07, v4.3.0-rc1~414^2~2) we share source group
assignments across targets to avoid copying and repeated work. However,
the VS 7 generator, still used for Fortran, relies on per-target
per-group source lists. Build them specifically for that case.
The deprecated Eclipse CDT4 extra generator had the same regression,
so fix it too.
Fixes: #27779
204 lines
5.0 KiB
C++
204 lines
5.0 KiB
C++
/* 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 "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();
|
|
}
|
|
|
|
std::set<std::string> const& cmSourceGroup::GetGroupFiles() const
|
|
{
|
|
return this->GroupFiles;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void cmSourceGroupFiles::Add(cmSourceGroup const* sg, cmSourceFile const* sf)
|
|
{
|
|
this->SourceFiles[sg].push_back(sf);
|
|
}
|
|
|
|
std::vector<cmSourceFile const*> const& cmSourceGroupFiles::GetSourceFiles(
|
|
cmSourceGroup const* sg) const
|
|
{
|
|
auto i = this->SourceFiles.find(sg);
|
|
if (i != this->SourceFiles.end()) {
|
|
return i->second;
|
|
}
|
|
static std::vector<cmSourceFile const*> const empty;
|
|
return empty;
|
|
}
|