[CMake] Project Grouping in a solution
Richard Moreland
rmoreland at acusoft.com
Thu Sep 27 10:01:54 EDT 2007
Attached is an updated patch that works with 2.4.7.
-Richard
Sylvain Benner wrote:
>>
>> Is there a way to group projects in a solution? Something like this
>> would be handy
>>
>> CMakeProject
>> --> ALL_BUILD
>> --> ZERO_CHECK
>> etc
>> lib
>> --> lib1
>> --> lib2
>>
>> Possibly something that follows the file system setup.
>> -Neal
> This topic has been addressed few days ago, a quick search in the
> mailing list archive would do the trick (
> http://www.cmake.org/pipermail/cmake/ )
> And here is the topic:
> http://www.cmake.org/pipermail/cmake/2007-September/016504.html
>
> --Sylvain
-------------- next part --------------
--- cmGlobalVisualStudio71Generator.cxx Mon Jul 16 17:16:42 2007
+++ cmGlobalVisualStudio71Generator.cxx Thu Aug 16 09:15:04 2007
@@ -228,6 +228,9 @@
}
}
}
+
+ WriteAdditionalProjectSections(fout, root, generators);
+
fout << "Global\n";
this->WriteSolutionConfigurations(fout);
fout << "\tGlobalSection(" << this->ProjectConfigurationSectionName
@@ -271,6 +274,8 @@
}
fout << "\tEndGlobalSection\n";
+ WriteAdditionalGlobalSections(fout, root, generators);
+
// Write the footer for the SLN file
this->WriteSLNFooter(fout);
}
--- cmGlobalVisualStudio71Generator.h Mon Jul 16 17:16:42 2007
+++ cmGlobalVisualStudio71Generator.h Thu Aug 16 09:15:13 2007
@@ -62,6 +62,12 @@
virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout);
+ virtual void WriteAdditionalGlobalSections(std::ostream& fout, cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators) {}
+
+ virtual void WriteAdditionalProjectSections(std::ostream& fout, cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators) {}
+
std::string ProjectConfigurationSectionName;
};
#endif
--- cmGlobalVisualStudio8Generator.cxx Mon Jul 16 17:16:42 2007
+++ cmGlobalVisualStudio8Generator.cxx Thu Aug 16 10:25:07 2007
@@ -170,10 +170,269 @@
}
//----------------------------------------------------------------------------
+std::vector<std::string> buildPathAndSubPathVector(const std::string& path)
+{
+ std::vector<std::string> ret;
+ ret.push_back(path);
+
+ int slashPos;
+ std::string workingPath = path;
+ while ((slashPos = workingPath.find_last_of("/")) != std::string::npos)
+ {
+ workingPath = workingPath.substr(0, slashPos);
+ ret.push_back(workingPath);
+ }
+
+ return ret;
+}
+
+//----------------------------------------------------------------------------
+std::string lastPathComponent(const std::string& path)
+{
+ int slashPos = path.find_last_of("/");
+ if (slashPos != std::string::npos)
+ {
+ return path.substr(slashPos+1, path.length() - slashPos);
+ }
+ return path;
+}
+
+//----------------------------------------------------------------------------
+std::string allButLastPathComponent(const std::string& path)
+{
+ int slashPos = path.find_last_of("/");
+ if (slashPos != std::string::npos)
+ {
+ return path.substr(0, slashPos);
+ }
+ return path;
+}
+
+//----------------------------------------------------------------------------
+std::string foobarPath(const std::string& path)
+{
+ return std::string("SOLUTION FOLDER: ") + path;
+}
+
+//----------------------------------------------------------------------------
+void cmGlobalVisualStudio8Generator::WriteAdditionalProjectSections(
+ std::ostream& fout, cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators)
+{
+ std::map<std::string, std::string> dspPathMap;
+ bool nestSolutionFolders =
+ cmSystemTools::IsOn(root->GetMakefile()->GetDefinition("NEST_SOLUTION_FOLDERS"));
+ nestSolutionFolders = true;
+
+ // Get the start directory with the trailing slash
+ std::string rootdir = root->GetMakefile()->GetStartOutputDirectory();
+ rootdir += "/";
+
+ // For each cmMakefile, create a VCProj for it, and
+ // add it to this SLN file
+ unsigned int i;
+ for(i = 0; i < generators.size(); ++i)
+ {
+ if(this->IsExcluded(root, generators[i]))
+ {
+ continue;
+ }
+ cmMakefile* mf = generators[i]->GetMakefile();
+
+ // Get the source directory from the makefile
+ std::string dir = mf->GetStartOutputDirectory();
+ // remove the home directory and / from the source directory
+ // this gives a relative path
+ cmSystemTools::ReplaceString(dir, rootdir.c_str(), "");
+
+ // Get the list of create dsp files names from the cmVCProjWriter, more
+ // than one dsp could have been created per input CMakeLists.txt file
+ // for each target
+ std::vector<std::string> dspnames =
+ static_cast<cmLocalVisualStudio7Generator *>(generators[i])
+ ->GetCreatedProjectNames();
+ cmTargets &tgts = generators[i]->GetMakefile()->GetTargets();
+ cmTargets::iterator l = tgts.begin();
+ for(std::vector<std::string>::iterator si = dspnames.begin();
+ l != tgts.end() && si != dspnames.end(); ++l)
+ {
+ // special handling for the current makefile
+ if(mf == generators[0]->GetMakefile())
+ {
+ dir = "."; // no subdirectory for project generated
+ }
+ // Write the project into the SLN file
+ if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
+ {
+ }
+ else if ((l->second.GetType() != cmTarget::INSTALL_FILES)
+ && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS))
+ {
+ if (si->c_str() != "")
+ {
+ if (l->first != "ALL_BUILD" && l->first != "INSTALL" && l->first != "RUN_TESTS" &&
+ l->first != "EDIT_CACHE" && l->first != "REBUILD_CACHE" && l->first != "PACKAGE" &&
+ l->first != "ZERO_CHECK" && l->first != "Continuous" && l->first != "Experimental" &&
+ l->first != "Nightly" && l->first != "NightlyMemoryCheck")
+ {
+ std::string path = generators[0]->Convert(mf->GetStartDirectory(), cmLocalGenerator::START);
+ dspPathMap.insert(std::make_pair(si->c_str(), path));
+ }
+ }
+ ++si;
+ }
+ }
+ }
+
+ // Construct the unique list of projects and guids to be written
+ std::map<std::string, std::string> pathGuidMap;
+ //std::vector<std::pair<std::string, std::string> > nestedProjects;
+
+ if (nestSolutionFolders)
+ {
+ std::map<std::string, std::string>::iterator dspPathIter, pathGuidIter;
+ for (dspPathIter = dspPathMap.begin(); dspPathIter != dspPathMap.end(); ++dspPathIter)
+ {
+ // Construct a vector of the path and all subpaths
+ std::vector<std::string> pathAndSubPaths = buildPathAndSubPathVector(dspPathIter->second);
+ //SystemTools::SplitString(dspPathIter->second, '/', true);
+
+ // For each path, create a guid and insert it into pathGuidMap if it is unique
+ std::vector<std::string>::iterator pathIt;
+ for (pathIt = pathAndSubPaths.begin(); pathIt != pathAndSubPaths.end(); ++pathIt)
+ {
+ pathGuidIter = pathGuidMap.find(*pathIt);
+ if (pathGuidIter == pathGuidMap.end())
+ {
+ // Insert it
+ CreateGUID(foobarPath(*pathIt).c_str());
+ std::string guid = GetGUID(foobarPath(*pathIt).c_str());
+ pathGuidMap.insert(std::make_pair(*pathIt, guid));
+ }
+ else
+ {
+ // Already created
+ }
+ }
+ }
+
+ // Write out all of the new projects, one per unique path component
+ for (pathGuidIter = pathGuidMap.begin(); pathGuidIter != pathGuidMap.end(); ++pathGuidIter)
+ {
+ std::string path = pathGuidIter->first;
+ std::string guid = pathGuidIter->second;
+ std::string lastPartOfPath = lastPathComponent(path);
+ if (lastPartOfPath == ".")
+ {
+ lastPartOfPath = "Root";
+ }
+ fout << "Project(\"" << "{2150E333-8FDC-42A3-9474-1A3956D46DE8}" << "\") = \""
+ << lastPartOfPath << "\", \"" << lastPartOfPath << "\", \"{" << guid << "}\"\n";
+ fout << "EndProject\n";
+
+ std::string parentPath = allButLastPathComponent(path);
+ if (parentPath != path)
+ {
+ std::string parentGuid = GetGUID(foobarPath(parentPath).c_str());
+ nestedProjects.push_back(std::make_pair(guid, parentGuid));
+ }
+ }
+
+ if (nestSolutionFolders)
+ {
+ std::vector<cmLocalGenerator*>& children = root->GetChildren();
+ std::vector<cmLocalGenerator*>::iterator it;
+ for (it = children.begin(); it != children.end(); ++it)
+ {
+ cmLocalGenerator* lg = *it;
+ std::string rl = lg->Convert("", cmLocalGenerator::START, cmLocalGenerator::SHELL, true);
+ }
+
+ for(i = 0; i < generators.size(); ++i)
+ {
+ cmMakefile* mf = generators[i]->GetMakefile();
+ cmLocalVisualStudio7Generator* pg =
+ static_cast<cmLocalVisualStudio7Generator*>(generators[i]);
+ // Get the list of create dsp files names from the cmVCProjWriter, more
+ // than one dsp could have been created per input CMakeLists.txt file
+ // for each target
+ std::vector<std::string> dspnames =
+ static_cast<cmLocalVisualStudio7Generator *>(generators[i])
+ ->GetCreatedProjectNames();
+ cmTargets &tgts = pg->GetMakefile()->GetTargets();
+ cmTargets::iterator l = tgts.begin();
+ std::string dir = mf->GetStartDirectory();
+ for(std::vector<std::string>::iterator si = dspnames.begin();
+ l != tgts.end() && si != dspnames.end(); ++l)
+ {
+ if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
+ {
+ // TODO
+ // Does this matter for the organization? Perhaps we could group them
+ // under an External Projects folder
+ }
+ else if ((l->second.GetType() != cmTarget::INSTALL_FILES)
+ && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS))
+ {
+ if (si->c_str() != "")
+ {
+ std::map<std::string, std::string>::iterator pathGuidIter;
+ std::string path = generators[0]->Convert(dir.c_str(), cmLocalGenerator::START);
+ pathGuidIter = pathGuidMap.find(path);
+ if (pathGuidIter != pathGuidMap.end())
+ {
+ // This find is to make sure we don't add things like RUN_TESTS
+ std::map<std::string, std::string>::iterator dspIter;
+ dspIter = dspPathMap.find(si->c_str());
+ if (dspIter != dspPathMap.end())
+ {
+ std::string projGuid = GetGUID(si->c_str());
+ std::string pathGuid = pathGuidIter->second;
+ nestedProjects.push_back(std::make_pair(projGuid, pathGuid));
+ }
+ else
+ {
+ // Perhaps add it to some Default folder.. ?
+ }
+ }
+ }
+ }
+ ++si;
+ }
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmGlobalVisualStudio8Generator::WriteAdditionalGlobalSections(
+ std::ostream& fout, cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators)
+{
+ bool nestSolutionFolders =
+ cmSystemTools::IsOn(root->GetMakefile()->GetDefinition("NEST_SOLUTION_FOLDERS"));
+ nestSolutionFolders = true;
+
+ if (nestSolutionFolders)
+ {
+ fout << "\tGlobalSection(NestedProjects) = preSolution\n";
+ std::vector<std::pair<std::string, std::string> >::iterator npIter;
+ for (npIter = nestedProjects.begin(); npIter != nestedProjects.end(); ++npIter)
+ {
+ fout << "\t\t{" << npIter->first << "} = {" << npIter->second << "}\n";
+ }
+ fout << "\tEndGlobalSection\n";
+ }
+}
+
+//----------------------------------------------------------------------------
void cmGlobalVisualStudio8Generator::WriteSLNFile(
std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators)
{
+ // Reset nestedProjects
+ nestedProjects.clear();
+
// Make all targets depend on their respective project's build
// system check target.
unsigned int i;
--- cmGlobalVisualStudio8Generator.h Mon Jul 16 17:16:42 2007
+++ cmGlobalVisualStudio8Generator.h Thu Aug 16 09:16:08 2007
@@ -59,6 +59,15 @@
virtual void WriteProjectConfigurations(std::ostream& fout,
const char* name,
bool partOfDefaultBuild);
+
+ virtual void WriteAdditionalGlobalSections(std::ostream& fout, cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators);
+
+ virtual void WriteAdditionalProjectSections(std::ostream& fout, cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators);
+
+ std::vector<std::pair<std::string, std::string> > nestedProjects;
+
std::string PlatformName; // Win32 or x64
};
#endif
More information about the CMake
mailing list