From 9441f6cfb2fd78fc87c970f43fb4828a0cd4c5ea Mon Sep 17 00:00:00 2001 From: Eduard Voronkin Date: Fri, 12 Sep 2025 13:58:38 -0700 Subject: [PATCH] FASTBuild: improve IDE project structure Right now, all IDE projects are located at the top level which makes it pretty messy when there are a lot of them. With this change the generated IDE project will more closely mimic existing folder structure in the project. --- Source/cmGlobalFastbuildGenerator.cxx | 44 ++++++++++++++++++++++----- Source/cmGlobalFastbuildGenerator.h | 1 + 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/Source/cmGlobalFastbuildGenerator.cxx b/Source/cmGlobalFastbuildGenerator.cxx index a0eaaed8da..54760577dd 100644 --- a/Source/cmGlobalFastbuildGenerator.cxx +++ b/Source/cmGlobalFastbuildGenerator.cxx @@ -1453,11 +1453,12 @@ void cmGlobalFastbuildGenerator::AddGlobCheckExec() void cmGlobalFastbuildGenerator::WriteSolution() { std::string const solutionName = LocalGenerators[0]->GetProjectName(); - std::vector VSProjects; + std::map> VSProjects; + std::vector VSProjectsWithoutFolder; for (auto const& IDEProj : IDEProjects) { auto const VSProj = IDEProj.second.first; - VSProjects.emplace_back(VSProj.Alias); + VSProjects[VSProj.folder].emplace_back(VSProj.Alias); } WriteCommand("VSSolution", Quote("solution")); @@ -1469,7 +1470,32 @@ void cmGlobalFastbuildGenerator::WriteSolution() auto const& configs = IDEProjects.begin()->second.first.ProjectConfigs; WriteIDEProjectConfig(configs, "SolutionConfigs"); - WriteArray("SolutionProjects", Wrap(VSProjects), 1); + int folderNumber = 0; + std::vector folders; + for (auto& item : VSProjects) { + auto const& pathToFolder = item.first; + auto& projectsInFolder = item.second; + if (pathToFolder.empty()) { + std::move(projectsInFolder.begin(), projectsInFolder.end(), + std::back_inserter(VSProjectsWithoutFolder)); + } else { + std::string folderName = + cmStrCat("Folder_", std::to_string(++folderNumber)); + WriteStruct( + folderName, + { { "Path", Quote(pathToFolder) }, + { "Projects", + cmStrCat("{", cmJoin(Wrap(projectsInFolder), ","), "}") } }, + 1); + folders.emplace_back(std::move(folderName)); + } + } + if (!folders.empty()) { + WriteArray("SolutionFolders ", Wrap(folders, ".", ""), 1); + } + if (!VSProjectsWithoutFolder.empty()) { + WriteArray("SolutionProjects", Wrap(VSProjectsWithoutFolder), 1); + } *this->BuildFileStream << "}\n"; } @@ -1697,17 +1723,21 @@ void cmGlobalFastbuildGenerator::AddIDEProject(FastbuildTarget const& target, return; } auto& IDEProject = IDEProjects[target.BaseName]; + auto const relativeSubdir = cmSystemTools::RelativePath( + this->GetCMakeInstance()->GetHomeDirectory(), target.BasePath); // VS auto& VSProject = IDEProject.first; VSProject.Alias = target.BaseName + "-vcxproj"; - VSProject.ProjectOutput = - cmStrCat("VisualStudio/Projects/", target.BaseName + ".vcxproj"); + VSProject.ProjectOutput = cmStrCat("VisualStudio/Projects/", relativeSubdir, + '/', target.BaseName + ".vcxproj"); VSProject.ProjectBasePath = target.BasePath; + VSProject.folder = relativeSubdir; // XCode auto& XCodeProject = IDEProject.second; XCodeProject.Alias = target.BaseName + "-xcodeproj"; - XCodeProject.ProjectOutput = cmStrCat( - "XCode/Projects/", target.BaseName + ".xcodeproj/project.pbxproj"); + XCodeProject.ProjectOutput = + cmStrCat("XCode/Projects/", relativeSubdir, '/', + target.BaseName + ".xcodeproj/project.pbxproj"); XCodeProject.ProjectBasePath = target.BasePath; IDEProjectConfig VSConfig; diff --git a/Source/cmGlobalFastbuildGenerator.h b/Source/cmGlobalFastbuildGenerator.h index e8c47a2f32..3c2e958111 100644 --- a/Source/cmGlobalFastbuildGenerator.h +++ b/Source/cmGlobalFastbuildGenerator.h @@ -247,6 +247,7 @@ struct XCodeProject : public IDEProjectCommon struct VCXProject : public IDEProjectCommon { + std::string folder; }; struct FastbuildLinkerNode