mirror of
https://github.com/reactos/CMake.git
synced 2025-02-21 12:20:48 +00:00
source_group: Add options create groups matching directory tree
Add `TREE` and `PREFIX` arguments to enable this behavior.
This commit is contained in:
parent
6154a2cddc
commit
b42330be21
@ -2,15 +2,27 @@ source_group
|
||||
------------
|
||||
|
||||
Define a grouping for source files in IDE project generation.
|
||||
There are two different signatures to create source groups.
|
||||
|
||||
.. code-block:: cmake
|
||||
::
|
||||
|
||||
source_group(<name> [FILES <src>...] [REGULAR_EXPRESSION <regex>])
|
||||
source_group(TREE <root> [PREFIX <prefix>] [FILES <src>...])
|
||||
|
||||
Defines a group into which sources will be placed in project files.
|
||||
This is intended to set up file tabs in Visual Studio.
|
||||
The options are:
|
||||
|
||||
``TREE``
|
||||
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>``.
|
||||
|
||||
``PREFIX``
|
||||
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
|
||||
@ -25,11 +37,13 @@ explicitly lists the file with ``FILES`` will be favored, if any.
|
||||
If no group explicitly lists the file, the *last* group whose
|
||||
regular expression matches the file will be favored.
|
||||
|
||||
The ``<name>`` of the group may contain backslashes to specify subgroups:
|
||||
The ``<name>`` of the group and ``<prefix>`` argument may contain backslashes
|
||||
to specify subgroups:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
source_group(outer\\inner ...)
|
||||
source_group(TREE <root> PREFIX sources\\inc ...)
|
||||
|
||||
For backwards compatibility, the short-hand signature
|
||||
|
||||
|
5
Help/release/dev/source_group-tree.rst
Normal file
5
Help/release/dev/source_group-tree.rst
Normal file
@ -0,0 +1,5 @@
|
||||
source_group-tree
|
||||
-----------------
|
||||
|
||||
* The :command:`source_group` command gained ``TREE`` and ``PREFIX``
|
||||
options to add groups following source tree directory structure.
|
@ -8,6 +8,99 @@
|
||||
#include "cmSourceGroup.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
namespace {
|
||||
const size_t RootIndex = 1;
|
||||
const size_t FilesWithoutPrefixKeywordIndex = 2;
|
||||
const size_t FilesWithPrefixKeywordIndex = 4;
|
||||
const size_t PrefixKeywordIdex = 2;
|
||||
|
||||
std::vector<std::string> tokenizePath(const std::string& path)
|
||||
{
|
||||
return cmSystemTools::tokenize(path, "\\/");
|
||||
}
|
||||
|
||||
std::string getFullFilePath(const std::string& currentPath,
|
||||
const std::string& path)
|
||||
{
|
||||
std::string fullPath = path;
|
||||
|
||||
if (!cmSystemTools::FileIsFullPath(path.c_str())) {
|
||||
fullPath = currentPath;
|
||||
fullPath += "/";
|
||||
fullPath += path;
|
||||
}
|
||||
|
||||
return cmSystemTools::CollapseFullPath(fullPath);
|
||||
}
|
||||
|
||||
std::set<std::string> getSourceGroupFilesPaths(
|
||||
const std::string& currentPath, const std::string& root,
|
||||
const std::vector<std::string>& files)
|
||||
{
|
||||
std::set<std::string> ret;
|
||||
const std::string::size_type rootLength = root.length();
|
||||
|
||||
for (size_t i = 0; i < files.size(); ++i) {
|
||||
const std::string fullPath = getFullFilePath(currentPath, files[i]);
|
||||
|
||||
ret.insert(fullPath.substr(rootLength + 1)); // +1 to also omnit last '/'
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmSourceGroup* addSourceGroup(const std::vector<std::string>& tokenizedPath,
|
||||
cmMakefile& makefile)
|
||||
{
|
||||
cmSourceGroup* sg;
|
||||
|
||||
sg = makefile.GetSourceGroup(tokenizedPath);
|
||||
if (!sg) {
|
||||
makefile.AddSourceGroup(tokenizedPath);
|
||||
sg = makefile.GetSourceGroup(tokenizedPath);
|
||||
if (!sg) {
|
||||
return CM_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
return sg;
|
||||
}
|
||||
|
||||
bool addFilesToItsSourceGroups(const std::set<std::string>& sgFilesPaths,
|
||||
const std::string& prefix, cmMakefile& makefile,
|
||||
std::string& errorMsg)
|
||||
{
|
||||
cmSourceGroup* sg;
|
||||
|
||||
for (std::set<std::string>::const_iterator it = sgFilesPaths.begin();
|
||||
it != sgFilesPaths.end(); ++it) {
|
||||
|
||||
std::vector<std::string> tokenizedPath;
|
||||
if (!prefix.empty()) {
|
||||
tokenizedPath = tokenizePath(prefix + '/' + *it);
|
||||
} else {
|
||||
tokenizedPath = tokenizePath(*it);
|
||||
}
|
||||
|
||||
if (tokenizedPath.size() > 1) {
|
||||
tokenizedPath.pop_back();
|
||||
|
||||
sg = addSourceGroup(tokenizedPath, makefile);
|
||||
|
||||
if (!sg) {
|
||||
errorMsg = "Could not create source group for file: " + *it;
|
||||
return false;
|
||||
}
|
||||
const std::string fullPath =
|
||||
getFullFilePath(makefile.GetCurrentSourceDirectory(), *it);
|
||||
sg->AddGroupFile(fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class cmExecutionStatus;
|
||||
|
||||
// cmSourceGroupCommand
|
||||
@ -19,6 +112,17 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args[0] == "TREE") {
|
||||
std::string error;
|
||||
|
||||
if (!processTree(args, error)) {
|
||||
this->SetError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string delimiter = "\\";
|
||||
if (this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER")) {
|
||||
delimiter = this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER");
|
||||
@ -82,3 +186,64 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmSourceGroupCommand::checkTreeArgumentsPreconditions(
|
||||
const std::vector<std::string>& args, std::string& errorMsg) const
|
||||
{
|
||||
if (args.size() == 1) {
|
||||
errorMsg = "TREE argument given without a root.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.size() < 3) {
|
||||
errorMsg = "Missing FILES arguments.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args[FilesWithoutPrefixKeywordIndex] != "FILES" &&
|
||||
args[PrefixKeywordIdex] != "PREFIX") {
|
||||
errorMsg = "Unknown argument \"" + args[2] +
|
||||
"\". Perhaps the FILES keyword is missing.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args[PrefixKeywordIdex] == "PREFIX" &&
|
||||
(args.size() < 5 || args[FilesWithPrefixKeywordIndex] != "FILES")) {
|
||||
errorMsg = "Missing FILES arguments.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmSourceGroupCommand::processTree(const std::vector<std::string>& args,
|
||||
std::string& errorMsg)
|
||||
{
|
||||
if (!checkTreeArgumentsPreconditions(args, errorMsg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string root = cmSystemTools::CollapseFullPath(args[RootIndex]);
|
||||
std::string prefix;
|
||||
size_t filesBegin = FilesWithoutPrefixKeywordIndex + 1;
|
||||
if (args[PrefixKeywordIdex] == "PREFIX") {
|
||||
prefix = args[PrefixKeywordIdex + 1];
|
||||
filesBegin = FilesWithPrefixKeywordIndex + 1;
|
||||
}
|
||||
|
||||
const std::vector<std::string> filesVector(args.begin() + filesBegin,
|
||||
args.end());
|
||||
|
||||
std::set<std::string> sourceGroupPaths = getSourceGroupFilesPaths(
|
||||
this->Makefile->GetCurrentSourceDirectory(), root, filesVector);
|
||||
|
||||
addFilesToItsSourceGroups(sourceGroupPaths, prefix, *(this->Makefile),
|
||||
errorMsg);
|
||||
|
||||
if (!errorMsg.empty()) {
|
||||
this->SetError(errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -36,6 +36,12 @@ public:
|
||||
* The name of the command as specified in CMakeList.txt.
|
||||
*/
|
||||
std::string GetName() const CM_OVERRIDE { return "source_group"; }
|
||||
|
||||
private:
|
||||
bool processTree(const std::vector<std::string>& args,
|
||||
std::string& errorMsg);
|
||||
bool checkTreeArgumentsPreconditions(const std::vector<std::string>& args,
|
||||
std::string& errorMsg) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -30,6 +30,17 @@ source_group(Base\\Sub1\\Base FILES bar.c)
|
||||
# a group without files, is currently not created
|
||||
source_group(EmptyGroup)
|
||||
|
||||
set(root ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_executable(SourceGroups main.c bar.c foo.c sub1/foo.c sub1/foobar.c baz.c README.txt)
|
||||
set(tree_files_without_prefix ${root}/sub1/tree_bar.c
|
||||
${root}/sub1/tree_baz.c
|
||||
${root}/sub1/tree_subdir/tree_foobar.c)
|
||||
|
||||
set(tree_files_with_prefix ${root}/tree_foo.c)
|
||||
|
||||
source_group(TREE ${root} FILES ${tree_files_without_prefix})
|
||||
|
||||
source_group(TREE ${root} PREFIX tree_root/subgroup FILES ${tree_files_with_prefix})
|
||||
|
||||
add_executable(SourceGroups main.c bar.c foo.c sub1/foo.c sub1/foobar.c baz.c
|
||||
${tree_files_with_prefix} ${tree_files_without_prefix} README.txt)
|
||||
|
@ -5,10 +5,17 @@ extern int bar(void);
|
||||
extern int foobar(void);
|
||||
extern int barbar(void);
|
||||
extern int baz(void);
|
||||
extern int tree_foo(void);
|
||||
extern int tree_bar(void);
|
||||
extern int tree_foobar(void);
|
||||
extern int tree_baz(void);
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("foo: %d bar: %d foobar: %d barbar: %d baz: %d\n", foo(), bar(),
|
||||
foobar(), barbar(), baz());
|
||||
|
||||
printf("tree_foo: %d tree_bar: %d tree_foobar: %d tree_baz: %d\n",
|
||||
tree_foo(), tree_bar(), tree_foobar(), tree_baz());
|
||||
return 0;
|
||||
}
|
||||
|
4
Tests/SourceGroups/sub1/tree_bar.c
Normal file
4
Tests/SourceGroups/sub1/tree_bar.c
Normal file
@ -0,0 +1,4 @@
|
||||
int tree_bar(void)
|
||||
{
|
||||
return 8;
|
||||
}
|
4
Tests/SourceGroups/sub1/tree_baz.c
Normal file
4
Tests/SourceGroups/sub1/tree_baz.c
Normal file
@ -0,0 +1,4 @@
|
||||
int tree_baz(void)
|
||||
{
|
||||
return 9;
|
||||
}
|
4
Tests/SourceGroups/sub1/tree_subdir/tree_foobar.c
Normal file
4
Tests/SourceGroups/sub1/tree_subdir/tree_foobar.c
Normal file
@ -0,0 +1,4 @@
|
||||
int tree_foobar(void)
|
||||
{
|
||||
return 7;
|
||||
}
|
4
Tests/SourceGroups/tree_foo.c
Normal file
4
Tests/SourceGroups/tree_foo.c
Normal file
@ -0,0 +1,4 @@
|
||||
int tree_foo(void)
|
||||
{
|
||||
return 6;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user