mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
source_group(): Add file set support
This commit is contained in:
@@ -4,52 +4,37 @@ source_group
|
||||
Define a grouping for source files in IDE project generation.
|
||||
There are two different signatures to create source groups.
|
||||
|
||||
.. code-block:: cmake
|
||||
Synopsis
|
||||
^^^^^^^^
|
||||
|
||||
source_group(<name> [FILES <src>...] [REGULAR_EXPRESSION <regex>])
|
||||
source_group(TREE <root> [PREFIX <prefix>] [FILES <src>...])
|
||||
.. parsed-literal::
|
||||
|
||||
source_group(`\<group\>`_ [FILES <src>...] [REGULAR_EXPRESSION <regex>]
|
||||
[FILE_SETS <fileset>... TARGET <target>]...)
|
||||
|
||||
source_group(`TREE`_ <root> [PREFIX <prefix>] [FILES <src>...])
|
||||
|
||||
Overview
|
||||
^^^^^^^^
|
||||
|
||||
Defines a group into which sources will be placed in project files.
|
||||
This is intended to set up file tabs in Visual Studio.
|
||||
The group is scoped in the directory where the command is called,
|
||||
and applies to sources in targets created in that directory.
|
||||
|
||||
The options are:
|
||||
The group is scoped in the directory where the command is called, and applies
|
||||
to sources in targets created in that directory.
|
||||
|
||||
``TREE``
|
||||
.. versionadded:: 3.8
|
||||
If the file is part of a file set, search for a group which explicitly lists
|
||||
this file set. If no group has been found or the file is not part of a file
|
||||
set, search for a group which explicitly lists the file.
|
||||
|
||||
CMake will automatically detect, from ``<src>`` files paths, source groups
|
||||
it needs to create, to keep structure of source groups analogically to the
|
||||
actual files and directories structure in the project. Paths of ``<src>``
|
||||
files will be cut to be relative to ``<root>``. The command fails if the
|
||||
paths within ``src`` do not start with ``root``.
|
||||
If the file set or the source file matches multiple groups, the *last* group
|
||||
that explicitly lists the file set with ``FILE_SETS`` or the file with
|
||||
``FILES`` will be favored, if any.
|
||||
|
||||
``PREFIX``
|
||||
.. versionadded:: 3.8
|
||||
|
||||
Source group and files located directly in ``<root>`` path, will be placed
|
||||
in ``<prefix>`` source groups.
|
||||
|
||||
``FILES``
|
||||
Any source file specified explicitly will be placed in group
|
||||
``<name>``. Relative paths are interpreted with respect to the
|
||||
current source directory.
|
||||
|
||||
.. versionadded:: 4.3
|
||||
Arguments to ``FILES`` may use
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
``REGULAR_EXPRESSION``
|
||||
Any source file whose name matches the regular expression will
|
||||
be placed in group ``<name>``.
|
||||
|
||||
If a source file matches multiple groups, the *last* group that
|
||||
explicitly lists the file with ``FILES`` will be favored, if any.
|
||||
If no group explicitly lists the file, the *last* group whose
|
||||
If no group explicitly lists the file set or the file, the *last* group whose
|
||||
regular expression matches the file will be favored.
|
||||
|
||||
The ``<name>`` of the group and ``<prefix>`` argument may contain forward
|
||||
The ``<group>`` and ``<prefix>`` arguments may contain forward
|
||||
slashes or backslashes to specify subgroups. Backslashes need to be escaped
|
||||
appropriately:
|
||||
|
||||
@@ -62,6 +47,78 @@ appropriately:
|
||||
.. versionadded:: 3.18
|
||||
Allow using forward slashes (``/``) to specify subgroups.
|
||||
|
||||
Commands
|
||||
^^^^^^^^
|
||||
|
||||
.. signature::
|
||||
source_group(<group> [FILES <src>...] [REGULAR_EXPRESSION <regex>]
|
||||
[FILE_SETS <fileset>... TARGET <target>]...)
|
||||
:target: <group>
|
||||
|
||||
The options are:
|
||||
|
||||
``<group>``
|
||||
The name of the group.
|
||||
|
||||
``FILES <src>...``
|
||||
Any source file specified explicitly will be placed in group
|
||||
``<group>``. Relative paths are interpreted with respect to the
|
||||
current source directory.
|
||||
|
||||
.. versionadded:: 4.3
|
||||
Arguments to ``FILES`` may use
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
``REGULAR_EXPRESSION <regex>``
|
||||
Any source file whose name matches the regular expression will
|
||||
be placed in group ``<group>``.
|
||||
|
||||
``FILE_SETS <fileset>...``
|
||||
.. versionadded:: 4.5
|
||||
|
||||
List of file sets. Files of these file sets will be placed in group
|
||||
``<group>``. Arguments to ``FILE_SETS`` may use
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
``TARGET <target>``
|
||||
.. versionadded:: 4.5
|
||||
|
||||
Associate the file sets declared with the previous ``FILE_SETS`` keyword
|
||||
with the target ``<target>``.
|
||||
|
||||
.. note::
|
||||
|
||||
The pattern ``FILE_SETS <fileset>... TARGET <target>`` can be repeated
|
||||
multiple times.
|
||||
|
||||
.. signature::
|
||||
source_group(TREE <root> [PREFIX <prefix>] [FILES <src>...])
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
The options are:
|
||||
|
||||
``TREE <root>``
|
||||
CMake will automatically detect, from ``<src>`` files paths, source groups
|
||||
it needs to create, to keep structure of source groups analogically to the
|
||||
actual files and directories structure in the project. Paths of ``<src>``
|
||||
files will be cut to be relative to ``<root>``. The command fails if the
|
||||
paths within ``src`` do not start with ``root``.
|
||||
|
||||
``PREFIX <prefix>``
|
||||
Source group and files located directly in ``<root>`` path, will be placed
|
||||
in ``<prefix>`` source groups.
|
||||
|
||||
``FILES <src>...``
|
||||
List of files used to create source group structure. Relative paths are
|
||||
interpreted with respect to the current source directory.
|
||||
|
||||
.. versionadded:: 4.3
|
||||
Arguments to ``FILES`` may use
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
Legacy Support
|
||||
^^^^^^^^^^^^^^
|
||||
For backwards compatibility, the short-hand signature
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
source_group-FILE_SET-support
|
||||
-----------------------------
|
||||
|
||||
* The :command:`source_group` command gains the support of the file sets.
|
||||
@@ -525,12 +525,12 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml)
|
||||
// get the files from the source lists then add them to the groups
|
||||
cmSourceGroupFiles sourceGroupFiles;
|
||||
std::vector<cmSourceFile*> files;
|
||||
target->GetSourceFiles(
|
||||
files, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
|
||||
cmValue config = makefile->GetDefinition("CMAKE_BUILD_TYPE");
|
||||
target->GetSourceFiles(files, *config);
|
||||
for (cmSourceFile* sf : files) {
|
||||
// Add the file to the list of sources.
|
||||
sourceGroupFiles.Add(lg->FindSourceGroup(sf->ResolveFullPath()),
|
||||
sf);
|
||||
sourceGroupFiles.Add(
|
||||
lg->FindSourceGroup(target.get(), sf, *config), sf);
|
||||
}
|
||||
|
||||
this->WriteGroups(makefile->GetSourceGroups(), sourceGroupFiles,
|
||||
|
||||
@@ -1926,8 +1926,8 @@ Json::Value Target::DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
|
||||
}
|
||||
}
|
||||
|
||||
if (cmSourceGroup const* sg =
|
||||
this->GT->LocalGenerator->FindSourceGroup(path)) {
|
||||
if (cmSourceGroup const* sg = this->GT->LocalGenerator->FindSourceGroup(
|
||||
this->GT, sf, this->Config)) {
|
||||
Json::ArrayIndex const groupIndex = this->AddSourceGroup(sg);
|
||||
source["sourceGroupIndex"] = groupIndex;
|
||||
this->SourceGroups[groupIndex].SourceIndexes.append(si);
|
||||
@@ -2017,8 +2017,8 @@ Json::Value Target::DumpInterfaceSource(std::string path, Json::ArrayIndex si,
|
||||
}
|
||||
}
|
||||
|
||||
if (cmSourceGroup const* sg =
|
||||
this->GT->LocalGenerator->FindSourceGroup(path)) {
|
||||
if (cmSourceGroup const* sg = this->GT->LocalGenerator->FindSourceGroup(
|
||||
this->GT, sf, this->Config)) {
|
||||
Json::ArrayIndex const groupIndex = this->AddSourceGroup(sg);
|
||||
source["sourceGroupIndex"] = groupIndex;
|
||||
this->SourceGroups[groupIndex].InterfaceSourceIndexes.append(si);
|
||||
|
||||
@@ -545,8 +545,8 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
|
||||
std::map<std::string, std::vector<cmSourceFile*>> groupFiles;
|
||||
std::set<std::string> groupNames;
|
||||
for (cmSourceFile* sf : sources) {
|
||||
cmSourceGroup const* sourceGroup =
|
||||
this->LocalGenerator->FindSourceGroup(sf->ResolveFullPath());
|
||||
cmSourceGroup const* sourceGroup = this->LocalGenerator->FindSourceGroup(
|
||||
this->GeneratorTarget, sf, this->ConfigName);
|
||||
std::string gn = sourceGroup->GetFullName();
|
||||
groupFiles[gn].push_back(sf);
|
||||
groupNames.insert(std::move(gn));
|
||||
|
||||
@@ -1810,7 +1810,6 @@ bool cmGlobalGenerator::Compute()
|
||||
|
||||
for (auto const& localGen : this->LocalGenerators) {
|
||||
localGen->ComputeHomeRelativeOutputPath();
|
||||
localGen->ComputeSourceGroupSearchIndex();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -4565,22 +4565,24 @@ bool cmGlobalXCodeGenerator::CreateGroups(
|
||||
}
|
||||
|
||||
auto addSourceToGroup = [this, >gt,
|
||||
&generator](std::string const& source) {
|
||||
cmSourceGroup const* sourceGroup = generator->FindSourceGroup(source);
|
||||
&generator](cmSourceFile const* source) {
|
||||
cmSourceGroup const* sourceGroup = generator->FindSourceGroup(
|
||||
gtgt.get(), source, this->CurrentConfigurationTypes.front());
|
||||
cmXCodeObject* pbxgroup =
|
||||
this->CreateOrGetPBXGroup(gtgt.get(), sourceGroup);
|
||||
std::string key = GetGroupMapKeyFromPath(gtgt.get(), source);
|
||||
std::string key =
|
||||
GetGroupMapKeyFromPath(gtgt.get(), source->GetFullPath());
|
||||
this->GroupMap[key] = pbxgroup;
|
||||
};
|
||||
|
||||
// Put cmSourceFile instances in proper groups:
|
||||
for (auto const& si : gtgt->GetAllConfigSources()) {
|
||||
cmSourceFile const* sf = si.Source;
|
||||
for (auto& si : gtgt->GetAllConfigSources()) {
|
||||
cmSourceFile* sf = si.Source;
|
||||
if (!sf->GetObjectLibrary().empty()) {
|
||||
// Object library files go on the link line instead.
|
||||
continue;
|
||||
}
|
||||
addSourceToGroup(sf->GetFullPath());
|
||||
addSourceToGroup(sf);
|
||||
}
|
||||
|
||||
// Add CMakeLists.txt file for user convenience.
|
||||
@@ -4589,8 +4591,9 @@ bool cmGlobalXCodeGenerator::CreateGroups(
|
||||
gtgt->GetLocalGenerator()->GetCurrentSourceDirectory());
|
||||
cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
|
||||
listfile, false, cmSourceFileLocationKind::Known);
|
||||
sf->ResolveFullPath();
|
||||
sf->SetSpecialSourceType(cmSourceFile::SpecialSourceType::CMakeLists);
|
||||
addSourceToGroup(sf->ResolveFullPath());
|
||||
addSourceToGroup(sf);
|
||||
}
|
||||
|
||||
// Add the Info.plist we are about to generate for an App Bundle.
|
||||
@@ -4598,9 +4601,10 @@ bool cmGlobalXCodeGenerator::CreateGroups(
|
||||
std::string plist = this->ComputeInfoPListLocation(gtgt.get());
|
||||
cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
|
||||
plist, true, cmSourceFileLocationKind::Known);
|
||||
sf->ResolveFullPath();
|
||||
sf->SetSpecialSourceType(
|
||||
cmSourceFile::SpecialSourceType::BundleInfoPlist);
|
||||
addSourceToGroup(sf->ResolveFullPath());
|
||||
addSourceToGroup(sf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-17
@@ -9,7 +9,6 @@
|
||||
#include <cstdlib>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
@@ -4255,28 +4254,49 @@ std::string cmLocalGenerator::CreateSafeObjectFileName(
|
||||
return ssin;
|
||||
}
|
||||
|
||||
void cmLocalGenerator::ComputeSourceGroupSearchIndex()
|
||||
// search a the source group defined for the file set or the source itself
|
||||
// in case of match, result is stored in a cache to speed-up future searches
|
||||
cmSourceGroup* cmLocalGenerator::FindSourceGroup(
|
||||
cmGeneratorTarget const* target, cmSourceFile const* source,
|
||||
std::string const& config)
|
||||
{
|
||||
#if !defined(CMAKE_BOOTSTRAP)
|
||||
SourceGroupVector const& sourceGroups = this->Makefile->GetSourceGroups();
|
||||
std::string const& targetName = target->GetName();
|
||||
cmGeneratorFileSet const* fileSet =
|
||||
target->GetFileSetForSource(config, source);
|
||||
|
||||
// Build lookup index from sources to source groups
|
||||
std::queue<cmSourceGroup*> sgToVisit;
|
||||
for (auto const& group : sourceGroups) {
|
||||
cmSourceGroup* cmSourceGroup = group.get();
|
||||
sgToVisit.emplace(cmSourceGroup);
|
||||
}
|
||||
|
||||
while (!sgToVisit.empty()) {
|
||||
cmSourceGroup* sourceGroup = sgToVisit.front();
|
||||
sgToVisit.pop();
|
||||
for (auto const& sgChild : sourceGroup->GetGroupChildren()) {
|
||||
sgToVisit.emplace(sgChild.get());
|
||||
if (fileSet) {
|
||||
std::string fsName = fileSet->GetName();
|
||||
std::string const fsKey = cmStrCat(targetName, "::", fsName);
|
||||
auto const indexIt = this->SourceGroupSearchIndex.find(fsKey);
|
||||
if (indexIt != this->SourceGroupSearchIndex.cend()) {
|
||||
return indexIt->second;
|
||||
}
|
||||
for (std::string const& source : sourceGroup->GetGroupFiles()) {
|
||||
this->SourceGroupSearchIndex.emplace(source, sourceGroup);
|
||||
|
||||
cmSourceGroup* sourceGroup = cmSourceGroup::FindSourceGroup(
|
||||
targetName, fsName, this->Makefile->GetSourceGroups());
|
||||
if (sourceGroup) {
|
||||
this->SourceGroupSearchIndex.emplace(fsKey, sourceGroup);
|
||||
return sourceGroup;
|
||||
}
|
||||
}
|
||||
|
||||
// no source group defined for the file set or the source is not part of a
|
||||
// file set.
|
||||
// search for source group defined at source level
|
||||
auto const indexIt =
|
||||
this->SourceGroupSearchIndex.find(source->GetFullPath());
|
||||
if (indexIt != this->SourceGroupSearchIndex.cend()) {
|
||||
return indexIt->second;
|
||||
}
|
||||
|
||||
// look-up in source groups definitions
|
||||
return this->FindSourceGroup(source->GetFullPath());
|
||||
#else
|
||||
static_cast<void>(target);
|
||||
static_cast<void>(source);
|
||||
static_cast<void>(config);
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -622,14 +622,12 @@ public:
|
||||
|
||||
std::string CreateSafeObjectFileName(std::string const& sin) const;
|
||||
|
||||
/**
|
||||
* Build the search index from source files to source groups
|
||||
*/
|
||||
void ComputeSourceGroupSearchIndex();
|
||||
|
||||
/**
|
||||
* find what source group this source is in
|
||||
*/
|
||||
cmSourceGroup* FindSourceGroup(cmGeneratorTarget const* target,
|
||||
cmSourceFile const* source,
|
||||
std::string const& config);
|
||||
cmSourceGroup* FindSourceGroup(std::string const& source);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1427,7 +1427,11 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
|
||||
}
|
||||
}
|
||||
// Add the file to the list of sources.
|
||||
sourceGroupFiles.Add(this->FindSourceGroup(sf->GetFullPath()), sf);
|
||||
sourceGroupFiles.Add(
|
||||
this->FindSourceGroup(
|
||||
target, sf,
|
||||
configs.empty() ? "" : configs[sources.Sources[si].Configs.front()]),
|
||||
sf);
|
||||
}
|
||||
|
||||
// open the project
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <cm/memory>
|
||||
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmList.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
|
||||
class cmSourceGroupInternals
|
||||
@@ -43,10 +44,20 @@ void cmSourceGroup::ResolveGenex(cmLocalGenerator* lg,
|
||||
{
|
||||
std::set<std::string> files;
|
||||
|
||||
for (std::string const& file : this->GroupFiles) {
|
||||
files.emplace(cmGeneratorExpression::Evaluate(file, lg, config));
|
||||
for (auto& pair : this->GroupFileSets) {
|
||||
files.clear();
|
||||
for (std::string const& fileSet : pair.second) {
|
||||
cmList list{ cmGeneratorExpression::Evaluate(fileSet, lg, config) };
|
||||
files.insert(list.begin(), list.end());
|
||||
}
|
||||
pair.second = std::move(files);
|
||||
}
|
||||
|
||||
files.clear();
|
||||
for (std::string const& file : this->GroupFiles) {
|
||||
cmList list{ cmGeneratorExpression::Evaluate(file, lg, config) };
|
||||
files.insert(list.begin(), list.end());
|
||||
}
|
||||
this->GroupFiles = std::move(files);
|
||||
|
||||
if (!this->Internal) {
|
||||
@@ -63,6 +74,13 @@ void cmSourceGroup::AddGroupFile(std::string const& name)
|
||||
this->GroupFiles.insert(name);
|
||||
}
|
||||
|
||||
void cmSourceGroup::AddGroupFileSets(std::string const& target,
|
||||
std::set<std::string> const& fileSets)
|
||||
{
|
||||
auto& fs = this->GroupFileSets[target];
|
||||
fs.insert(fileSets.begin(), fileSets.end());
|
||||
}
|
||||
|
||||
std::string const& cmSourceGroup::GetName() const
|
||||
{
|
||||
return this->Name;
|
||||
@@ -88,6 +106,11 @@ std::set<std::string> const& cmSourceGroup::GetGroupFiles() const
|
||||
{
|
||||
return this->GroupFiles;
|
||||
}
|
||||
std::map<std::string, std::set<std::string>> const&
|
||||
cmSourceGroup::GetGroupFileSets() const
|
||||
{
|
||||
return this->GroupFileSets;
|
||||
}
|
||||
|
||||
void cmSourceGroup::AddChild(std::unique_ptr<cmSourceGroup> child)
|
||||
{
|
||||
@@ -151,6 +174,23 @@ cmSourceGroup* cmSourceGroup::MatchChildrenRegex(std::string const& name) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cmSourceGroup* cmSourceGroup::MatchChildrenFileSets(std::string const& target,
|
||||
std::string const& fileSet)
|
||||
{
|
||||
auto item = this->GroupFileSets.find(target);
|
||||
if (item != this->GroupFileSets.end() &&
|
||||
item->second.find(fileSet) != item->second.end()) {
|
||||
return this;
|
||||
}
|
||||
for (auto const& group : this->Internal->GroupChildren) {
|
||||
if (cmSourceGroup* result =
|
||||
group->MatchChildrenFileSets(target, fileSet)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SourceGroupVector const& cmSourceGroup::GetGroupChildren() const
|
||||
{
|
||||
return this->Internal->GroupChildren;
|
||||
@@ -160,7 +200,7 @@ SourceGroupVector const& cmSourceGroup::GetGroupChildren() const
|
||||
* 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
|
||||
* non-inherited source_group() commands will have precedence over
|
||||
* inherited ones.
|
||||
*/
|
||||
cmSourceGroup* cmSourceGroup::FindSourceGroup(std::string const& source,
|
||||
@@ -186,6 +226,27 @@ cmSourceGroup* cmSourceGroup::FindSourceGroup(std::string const& source,
|
||||
return groups.data()->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a source group whose matches the target and file set.
|
||||
* 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& target,
|
||||
std::string const& fileSet,
|
||||
SourceGroupVector const& groups)
|
||||
{
|
||||
// First search for a group that lists the file set explicitly.
|
||||
for (auto sg = groups.rbegin(); sg != groups.rend(); ++sg) {
|
||||
if (cmSourceGroup* result =
|
||||
(*sg)->MatchChildrenFileSets(target, fileSet)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void cmSourceGroupFiles::Add(cmSourceGroup const* sg, cmSourceFile const* sf)
|
||||
{
|
||||
this->SourceFiles[sg].push_back(sf);
|
||||
|
||||
@@ -56,6 +56,12 @@ public:
|
||||
*/
|
||||
void AddGroupFile(std::string const& name);
|
||||
|
||||
/**
|
||||
* Add file sets to the explicit list of file sets for this group.
|
||||
*/
|
||||
void AddGroupFileSets(std::string const& target,
|
||||
std::set<std::string> const& fileSets);
|
||||
|
||||
/**
|
||||
* Add child to this sourcegroup
|
||||
*/
|
||||
@@ -103,10 +109,21 @@ public:
|
||||
*/
|
||||
cmSourceGroup* MatchChildrenRegex(std::string const& name) const;
|
||||
|
||||
/**
|
||||
* Check if the given name matches this group's explicit file list
|
||||
* in children.
|
||||
*/
|
||||
cmSourceGroup* MatchChildrenFileSets(std::string const& target,
|
||||
std::string const& fileSet);
|
||||
|
||||
/**
|
||||
* Get the set of file names explicitly added to this source group.
|
||||
*/
|
||||
std::set<std::string> const& GetGroupFiles() const;
|
||||
/**
|
||||
* Get the set of file sets names explicitly added to this source group.
|
||||
*/
|
||||
std::map<std::string, std::set<std::string>> const& GetGroupFileSets() const;
|
||||
|
||||
SourceGroupVector const& GetGroupChildren() const;
|
||||
|
||||
@@ -115,6 +132,13 @@ public:
|
||||
*/
|
||||
static cmSourceGroup* FindSourceGroup(std::string const& source,
|
||||
SourceGroupVector const& groups);
|
||||
/**
|
||||
* Given a source group collection, find the source group for a given
|
||||
* target/file set.
|
||||
*/
|
||||
static cmSourceGroup* FindSourceGroup(std::string const& target,
|
||||
std::string const& fileSet,
|
||||
SourceGroupVector const& groups);
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -134,6 +158,11 @@ private:
|
||||
*/
|
||||
std::set<std::string> GroupFiles;
|
||||
|
||||
/**
|
||||
* Set of file Sets indexed by target explicitly added to this group.
|
||||
*/
|
||||
std::map<std::string, std::set<std::string>> GroupFileSets;
|
||||
|
||||
std::unique_ptr<cmSourceGroupInternals> Internal;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmSourceGroupCommand.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
@@ -22,6 +25,7 @@
|
||||
#include "cmSourceGroup.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
|
||||
namespace {
|
||||
template <typename Args>
|
||||
@@ -127,8 +131,12 @@ bool cmSourceGroupCommand(std::vector<std::string> const& args,
|
||||
cm::optional<std::string> GroupName;
|
||||
cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Files;
|
||||
cm::optional<std::string> Regex;
|
||||
cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>>
|
||||
FileSets;
|
||||
cm::optional<ArgumentParser::NonEmpty<std::string>> Tree;
|
||||
cm::optional<ArgumentParser::MaybeEmpty<std::string>> Prefix;
|
||||
|
||||
std::map<std::string, std::set<std::string>> FileSetsPerTarget;
|
||||
};
|
||||
|
||||
auto unsupportedKeyword =
|
||||
@@ -147,6 +155,21 @@ bool cmSourceGroupCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
return ArgumentParser::Continue::No;
|
||||
};
|
||||
auto handleTarget = [](Arguments& result,
|
||||
cm::string_view value) -> ArgumentParser::Continue {
|
||||
if (!result.FileSets) {
|
||||
result.AddKeywordError(
|
||||
"TARGET", cmStrCat("FILE_SETS is required for TARGET ", value, '.'));
|
||||
return ArgumentParser::Continue::No;
|
||||
}
|
||||
if (!result.FileSets->empty()) {
|
||||
result.FileSetsPerTarget[std::string{ value }].insert(
|
||||
result.FileSets->begin(), result.FileSets->end());
|
||||
}
|
||||
result.FileSets.reset();
|
||||
|
||||
return ArgumentParser::Continue::Yes;
|
||||
};
|
||||
|
||||
std::vector<std::string> unexpectedArgs;
|
||||
auto parser =
|
||||
@@ -156,11 +179,15 @@ bool cmSourceGroupCommand(std::vector<std::string> const& args,
|
||||
// this is the TREE syntax
|
||||
parser.Bind("TREE"_s, &Arguments::Tree)
|
||||
.Bind("PREFIX"_s, &Arguments::Prefix)
|
||||
.Bind("REGULAR_EXPRESSION"_s, unsupportedKeyword);
|
||||
.Bind("REGULAR_EXPRESSION"_s, unsupportedKeyword)
|
||||
.Bind("FILE_SETS"_s, unsupportedKeyword)
|
||||
.Bind("TARGET"_s, unsupportedKeyword);
|
||||
} else {
|
||||
// assume that first argument is the group name
|
||||
parser.Bind(0, &Arguments::GroupName)
|
||||
.Bind("REGULAR_EXPRESSION"_s, handleRegex, 0)
|
||||
.Bind("FILE_SETS"_s, &Arguments::FileSets)
|
||||
.Bind("TARGET"_s, handleTarget)
|
||||
.Bind("TREE"_s, unsupportedKeyword)
|
||||
.Bind("PREFIX"_s, unsupportedKeyword);
|
||||
}
|
||||
@@ -177,6 +204,11 @@ bool cmSourceGroupCommand(std::vector<std::string> const& args,
|
||||
cmSystemTools::SetFatalErrorOccurred();
|
||||
return false;
|
||||
}
|
||||
if (!parsedArgs.Tree && parsedArgs.FileSets) {
|
||||
status.SetError(cmStrCat("TARGET is required for FILE_SETS ",
|
||||
cmJoin(*parsedArgs.FileSets, ", "), '.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parsedArgs.Tree) {
|
||||
if (!ProcessTree(parsedArgs, status)) {
|
||||
@@ -184,7 +216,8 @@ bool cmSourceGroupCommand(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!parsedArgs.Files && !parsedArgs.Regex) {
|
||||
if (!parsedArgs.Files && !parsedArgs.Regex &&
|
||||
parsedArgs.FileSetsPerTarget.empty()) {
|
||||
// group is not created
|
||||
return true;
|
||||
}
|
||||
@@ -210,6 +243,34 @@ bool cmSourceGroupCommand(std::vector<std::string> const& args,
|
||||
cmSystemTools::CollapseFullPath(file, currentSourceDir));
|
||||
}
|
||||
}
|
||||
for (auto& item : parsedArgs.FileSetsPerTarget) {
|
||||
// check validity of arguments
|
||||
auto it = mf.GetTargets().find(item.first);
|
||||
if (it == mf.GetTargets().end()) {
|
||||
mf.IssueDiagnostic(
|
||||
cmDiagnostics::CMD_AUTHOR,
|
||||
cmStrCat(
|
||||
"TARGET \"", item.first,
|
||||
"\" is not defined in this directory. It will be ignored."));
|
||||
continue;
|
||||
}
|
||||
|
||||
cmTarget const& target = it->second;
|
||||
for (auto it2 = item.second.begin(); it2 != item.second.end();) {
|
||||
if (!target.GetFileSet(*it2)) {
|
||||
mf.IssueDiagnostic(cmDiagnostics::CMD_AUTHOR,
|
||||
cmStrCat("FILE_SET \"", *it2,
|
||||
"\" is not known for TARGET \"",
|
||||
item.first, "\". It will ignored."));
|
||||
it2 = item.second.erase(it2);
|
||||
} else {
|
||||
++it2;
|
||||
}
|
||||
}
|
||||
if (!item.second.empty()) {
|
||||
sg->AddGroupFileSets(item.first, item.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -2006,17 +2006,18 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
|
||||
|
||||
std::set<cmSourceGroup const*> groupsUsed;
|
||||
for (cmGeneratorTarget::AllConfigSource const& si : sources) {
|
||||
std::string const& source = si.Source->GetFullPath();
|
||||
cmSourceGroup const* sourceGroup =
|
||||
this->LocalGenerator->FindSourceGroup(source);
|
||||
cmSourceGroup const* sourceGroup = this->LocalGenerator->FindSourceGroup(
|
||||
this->GeneratorTarget, si.Source,
|
||||
this->Configurations.empty() ? ""
|
||||
: this->Configurations[si.Configs.front()]);
|
||||
groupsUsed.insert(sourceGroup);
|
||||
}
|
||||
|
||||
if (cmSourceFile const* srcCMakeLists =
|
||||
this->LocalGenerator->CreateVCProjBuildRule()) {
|
||||
std::string const& source = srcCMakeLists->GetFullPath();
|
||||
cmSourceGroup const* sourceGroup =
|
||||
this->LocalGenerator->FindSourceGroup(source);
|
||||
cmSourceGroup const* sourceGroup = this->LocalGenerator->FindSourceGroup(
|
||||
this->GeneratorTarget, srcCMakeLists,
|
||||
this->Configurations.empty() ? "" : this->Configurations.front());
|
||||
groupsUsed.insert(sourceGroup);
|
||||
}
|
||||
|
||||
@@ -2175,8 +2176,9 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources(
|
||||
for (ToolSource const& s : sources) {
|
||||
cmSourceFile const* sf = s.SourceFile;
|
||||
std::string const& source = sf->GetFullPath();
|
||||
cmSourceGroup const* sourceGroup =
|
||||
this->LocalGenerator->FindSourceGroup(source);
|
||||
cmSourceGroup const* sourceGroup = this->LocalGenerator->FindSourceGroup(
|
||||
this->GeneratorTarget, sf,
|
||||
this->Configurations.empty() ? "" : this->Configurations.front());
|
||||
std::string const& filter = sourceGroup->GetFullName();
|
||||
std::string path = this->ConvertPath(source, s.RelativePath);
|
||||
ConvertToWindowsSlash(path);
|
||||
@@ -6095,8 +6097,9 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
|
||||
std::string const& fullFileName = source->GetFullPath();
|
||||
std::string const& srcDir = this->Makefile->GetCurrentSourceDirectory();
|
||||
std::string const& binDir = this->Makefile->GetCurrentBinaryDirectory();
|
||||
cmSourceGroup const* sourceGroup =
|
||||
this->LocalGenerator->FindSourceGroup(fullFileName);
|
||||
cmSourceGroup const* sourceGroup = this->LocalGenerator->FindSourceGroup(
|
||||
this->GeneratorTarget, source,
|
||||
this->Configurations.empty() ? "" : this->Configurations.front());
|
||||
if (sourceGroup && !sourceGroup->GetFullName().empty()) {
|
||||
sourceGroupedFile =
|
||||
cmStrCat(sourceGroup->GetFullName(), '/',
|
||||
|
||||
@@ -9,3 +9,15 @@ CMake Warning \(author\) at IgnoredKeywords\.cmake:[0-9]+ \(source_group\):
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.
|
||||
|
||||
CMake Warning \(author\) at IgnoredKeywords\.cmake:[0-9]+ \(source_group\):
|
||||
keyword "FILE_SETS" will be ignored in this context\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.
|
||||
|
||||
CMake Warning \(author\) at IgnoredKeywords\.cmake:[0-9]+ \(source_group\):
|
||||
keyword "TARGET" will be ignored in this context\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
source_group(foo PREFIX bar)
|
||||
|
||||
source_group(TREE foo REGULAR_EXPRESSION ".*")
|
||||
source_group(TREE foo REGULAR_EXPRESSION ".*" FILE_SETS fs TARGET t)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,6 @@
|
||||
CMake Error at MissingFILE_SETS\.cmake:[0-9]+ \(source_group\):
|
||||
source_group given invalid argument:
|
||||
|
||||
TARGET: FILE_SETS is required for TARGET bar\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
source_group(foo TARGET bar)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error at MissingTARGET\.cmake:[0-9]+ \(source_group\):
|
||||
source_group TARGET is required for FILE_SETS bar\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
source_group(foo FILE_SETS bar)
|
||||
@@ -4,3 +4,7 @@ include(RunCMake)
|
||||
run_cmake(MixedSignatures)
|
||||
run_cmake(WrongRegex)
|
||||
run_cmake(IgnoredKeywords)
|
||||
run_cmake(MissingFILE_SETS)
|
||||
run_cmake(UnknownFILE_SET)
|
||||
run_cmake(MissingTARGET)
|
||||
run_cmake(UnknownTARGET)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
CMake Warning \(author\) at UnknownFILE_SET\.cmake:[0-9]+ \(source_group\):
|
||||
FILE_SET "bar" is not known for TARGET "bar"\. It will ignored\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library(bar empty.c)
|
||||
|
||||
source_group(foo FILE_SETS bar TARGET bar)
|
||||
@@ -0,0 +1,5 @@
|
||||
CMake Warning \(author\) at UnknownTARGET\.cmake:[0-9]+ \(source_group\):
|
||||
TARGET "bar" is not defined in this directory\. It will be ignored.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
source_group(foo FILE_SETS bar TARGET bar)
|
||||
Reference in New Issue
Block a user