diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index 75b74674e..5ff3f12c8 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -156,12 +156,24 @@ cmLocalGenerator *cmGlobalVisualStudio6Generator::CreateLocalGenerator() void cmGlobalVisualStudio6Generator::Generate() { + // collect sub-projects + this->CollectSubprojects(); + // add a special target that depends on ALL projects for easy build - // of Debug only + // of one configuration only. std::vector srcs; - m_LocalGenerators[0]->GetMakefile()-> - AddUtilityCommand("ALL_BUILD", "echo","\"Build all projects\"",false,srcs); - + std::map >::iterator it; + for(it = m_SubProjectMap.begin(); it!= m_SubProjectMap.end(); ++it) + { + std::vector& gen = it->second; + // add the ALL_BUILD to the first local generator of each project + if(gen.size()) + { + gen[0]->GetMakefile()-> + AddUtilityCommand("ALL_BUILD", "echo","\"Build all projects\"",false,srcs); + } + } + // add the Run Tests command this->SetupTests(); @@ -172,30 +184,177 @@ void cmGlobalVisualStudio6Generator::Generate() this->OutputDSWFile(); } -// output the DSW file -void cmGlobalVisualStudio6Generator::OutputDSWFile() -{ - // create the dsw file name - std::string fname; - fname = m_CMakeInstance->GetStartOutputDirectory(); +// populate the m_SubProjectMap +void cmGlobalVisualStudio6Generator::CollectSubprojects() +{ + unsigned int i; + for(i = 0; i < m_LocalGenerators.size(); ++i) + { + std::string name = m_LocalGenerators[i]->GetMakefile()->GetProjectName(); + m_SubProjectMap[name].push_back(m_LocalGenerators[i]); + std::vector const& pprojects + = m_LocalGenerators[i]->GetMakefile()->GetParentProjects(); + for(int k =0; k < pprojects.size(); ++k) + { + m_SubProjectMap[pprojects[k]].push_back(m_LocalGenerators[i]); + } + } +} + +// Write a DSW file to the stream +void cmGlobalVisualStudio6Generator::WriteDSWFile(std::ostream& fout, + std::vector& generators) +{ + // Write out the header for a DSW file + this->WriteDSWHeader(fout); + + // Get the home directory with the trailing slash + std::string homedir = m_CMakeInstance->GetHomeDirectory(); + homedir += "/"; + + unsigned int i; + bool doneAllBuild = false; + bool doneRunTests = false; + for(i = 0; i < generators.size(); ++i) + { + cmMakefile* mf = generators[i]->GetMakefile(); + + // Get the source directory from the makefile + std::string dir = mf->GetStartDirectory(); + // remove the home directory and / from the source directory + // this gives a relative path + cmSystemTools::ReplaceString(dir, homedir.c_str(), ""); + + // Get the list of create dsp files names from the LocalGenerator, more + // than one dsp could have been created per input CMakeLists.txt file + // for each target + std::vector dspnames = + static_cast(generators[i]) + ->GetCreatedProjectNames(); + cmTargets &tgts = generators[i]->GetMakefile()->GetTargets(); + cmTargets::iterator l = tgts.begin(); + for(std::vector::iterator si = dspnames.begin(); + l != tgts.end(); ++l) + { + // special handling for the current makefile + if(mf == generators[0]->GetMakefile()) + { + dir = "."; // no subdirectory for project generated + // if this is the special ALL_BUILD utility, then + // make it depend on every other non UTILITY project. + // This is done by adding the names to the GetUtilities + // vector on the makefile + if(l->first == "ALL_BUILD" && !doneAllBuild) + { + unsigned int j; + for(j = 0; j < generators.size(); ++j) + { + const cmTargets &atgts = + generators[j]->GetMakefile()->GetTargets(); + for(cmTargets::const_iterator al = atgts.begin(); + al != atgts.end(); ++al) + { + if (al->second.IsInAll()) + { + if (al->second.GetType() == cmTarget::UTILITY) + { + l->second.AddUtility(al->first.c_str()); + } + else + { + l->second.AddLinkLibrary(al->first, cmTarget::GENERAL); + } + } + } + } + } + } + // Write the project into the DSW file + if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0) + { + cmCustomCommand cc = l->second.GetPreLinkCommands()[0]; + + // dodgy use of the cmCustomCommand's members to store the + // arguments from the INCLUDE_EXTERNAL_MSPROJECT command + std::vector stuff = cc.GetDepends(); + std::vector depends; + depends.push_back(cc.GetOutput()); + this->WriteExternalProject(fout, stuff[0].c_str(), stuff[1].c_str(), depends); + ++si; + } + else + { + if ((l->second.GetType() != cmTarget::INSTALL_FILES) + && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)) + { + bool skip = false; + // skip ALL_BUILD and RUN_TESTS if they have already been added + if(l->first == "ALL_BUILD" ) + { + if(doneAllBuild) + { + skip = true; + } + else + { + doneAllBuild = true; + } + } + if(l->first == "RUN_TESTS") + { + if(doneRunTests) + { + skip = true; + } + else + { + doneRunTests = true; + } + } + if(!skip) + { + this->WriteProject(fout, si->c_str(), dir.c_str(),l->second); + } + ++si; + } + } + } + } + + // Write the footer for the DSW file + this->WriteDSWFooter(fout); +} + +void cmGlobalVisualStudio6Generator::OutputDSWFile(const char* projectName, + std::vector& generators) +{ + if(generators.size() == 0) + { + return; + } + std::string fname = generators[0]->GetMakefile()->GetStartOutputDirectory(); fname += "/"; - if(strlen(m_LocalGenerators[0]->GetMakefile()->GetProjectName())) - { - fname += m_LocalGenerators[0]->GetMakefile()->GetProjectName(); - } - else - { - fname += "Project"; - } + fname += generators[0]->GetMakefile()->GetProjectName(); fname += ".dsw"; std::ofstream fout(fname.c_str()); if(!fout) { - cmSystemTools::Error("Error can not open DSW file for write: " - ,fname.c_str()); + cmSystemTools::Error("Error can not open DSW file for write: ", + fname.c_str()); return; } - this->WriteDSWFile(fout); + this->WriteDSWFile(fout, generators); +} + +// output the DSW file +void cmGlobalVisualStudio6Generator::OutputDSWFile() +{ + std::map >::iterator it; + for(it = m_SubProjectMap.begin(); it!= m_SubProjectMap.end(); ++it) + { + std::vector& gen = it->second; + this->OutputDSWFile(it->first.c_str(), it->second); + } } @@ -249,105 +408,19 @@ void cmGlobalVisualStudio6Generator::SetupTests() if (cmSystemTools::FileExists(fname.c_str())) { std::vector srcs; - m_LocalGenerators[0]->GetMakefile()-> - AddUtilityCommand("RUN_TESTS", ctest.c_str(), "-D $(IntDir)",false,srcs); - } - } -} - -// Write a DSW file to the stream -void cmGlobalVisualStudio6Generator::WriteDSWFile(std::ostream& fout) -{ - // Write out the header for a DSW file - this->WriteDSWHeader(fout); - - - // Get the home directory with the trailing slash - std::string homedir = m_CMakeInstance->GetHomeDirectory(); - homedir += "/"; - - unsigned int i; - for(i = 0; i < m_LocalGenerators.size(); ++i) - { - cmMakefile* mf = m_LocalGenerators[i]->GetMakefile(); - - // Get the source directory from the makefile - std::string dir = mf->GetStartDirectory(); - // remove the home directory and / from the source directory - // this gives a relative path - cmSystemTools::ReplaceString(dir, homedir.c_str(), ""); - - // Get the list of create dsp files names from the LocalGenerator, more - // than one dsp could have been created per input CMakeLists.txt file - // for each target - std::vector dspnames = - static_cast(m_LocalGenerators[i]) - ->GetCreatedProjectNames(); - cmTargets &tgts = m_LocalGenerators[i]->GetMakefile()->GetTargets(); - cmTargets::iterator l = tgts.begin(); - for(std::vector::iterator si = dspnames.begin(); - l != tgts.end(); ++l) - { - // special handling for the current makefile - if(mf == m_LocalGenerators[0]->GetMakefile()) + std::map >::iterator it; + for(it = m_SubProjectMap.begin(); it!= m_SubProjectMap.end(); ++it) { - dir = "."; // no subdirectory for project generated - // if this is the special ALL_BUILD utility, then - // make it depend on every other non UTILITY project. - // This is done by adding the names to the GetUtilities - // vector on the makefile - if(l->first == "ALL_BUILD") + std::vector& gen = it->second; + // add the ALL_BUILD to the first local generator of each project + if(gen.size()) { - unsigned int j; - for(j = 0; j < m_LocalGenerators.size(); ++j) - { - const cmTargets &atgts = - m_LocalGenerators[j]->GetMakefile()->GetTargets(); - for(cmTargets::const_iterator al = atgts.begin(); - al != atgts.end(); ++al) - { - if (al->second.IsInAll()) - { - if (al->second.GetType() == cmTarget::UTILITY) - { - l->second.AddUtility(al->first.c_str()); - } - else - { - l->second.AddLinkLibrary(al->first, cmTarget::GENERAL); - } - } - } - } - } - } - // Write the project into the DSW file - if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0) - { - cmCustomCommand cc = l->second.GetPreLinkCommands()[0]; - - // dodgy use of the cmCustomCommand's members to store the - // arguments from the INCLUDE_EXTERNAL_MSPROJECT command - std::vector stuff = cc.GetDepends(); - std::vector depends; - depends.push_back(cc.GetOutput()); - this->WriteExternalProject(fout, stuff[0].c_str(), stuff[1].c_str(), depends); - ++si; - } - else - { - if ((l->second.GetType() != cmTarget::INSTALL_FILES) - && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)) - { - this->WriteProject(fout, si->c_str(), dir.c_str(),l->second); - ++si; + gen[0]->GetMakefile()-> + AddUtilityCommand("RUN_TESTS", ctest.c_str(), "-D $(IntDir)",false,srcs); } } } } - - // Write the footer for the DSW file - this->WriteDSWFooter(fout); } diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h index 4df1a7068..ff0d8a36d 100644 --- a/Source/cmGlobalVisualStudio6Generator.h +++ b/Source/cmGlobalVisualStudio6Generator.h @@ -68,8 +68,11 @@ public: * Generate the DSW workspace file. */ virtual void OutputDSWFile(); - + virtual void OutputDSWFile(const char* projectName, std::vector& generators); + virtual void WriteDSWFile(std::ostream& fout, + std::vector& generators); private: + void CollectSubprojects(); void GenerateConfigurations(cmMakefile* mf); void SetupTests(); void WriteDSWFile(std::ostream& fout); @@ -81,6 +84,7 @@ private: const char* name, const char* path, const std::vector& dependencies); void WriteDSWFooter(std::ostream& fout); + std::map > m_SubProjectMap; }; #endif diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 543519011..0d0eadeea 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -157,8 +157,17 @@ void cmGlobalVisualStudio7Generator::SetupTests() if (cmSystemTools::FileExists(fname.c_str())) { std::vector srcs; - m_LocalGenerators[0]->GetMakefile()-> - AddUtilityCommand("RUN_TESTS", ctest.c_str(), "-D $(IntDir)",false, srcs); + std::map >::iterator it; + for(it = m_SubProjectMap.begin(); it!= m_SubProjectMap.end(); ++it) + { + std::vector& gen = it->second; + // add the ALL_BUILD to the first local generator of each project + if(gen.size()) + { + gen[0]->GetMakefile()-> + AddUtilityCommand("RUN_TESTS", ctest.c_str(), "-D $(IntDir)",false,srcs); + } + } } } } @@ -233,11 +242,22 @@ void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf) void cmGlobalVisualStudio7Generator::Generate() { + // collect sub-projects + this->CollectSubprojects(); // add a special target that depends on ALL projects for easy build // of Debug only std::vector srcs; - m_LocalGenerators[0]->GetMakefile()-> - AddUtilityCommand("ALL_BUILD", "echo","\"Build all projects\"",false, srcs); + std::map >::iterator it; + for(it = m_SubProjectMap.begin(); it!= m_SubProjectMap.end(); ++it) + { + std::vector& gen = it->second; + // add the ALL_BUILD to the first local generator of each project + if(gen.size()) + { + gen[0]->GetMakefile()-> + AddUtilityCommand("ALL_BUILD", "echo","\"Build all projects\"",false,srcs); + } + } // add the Run Tests command this->SetupTests(); @@ -249,42 +269,42 @@ void cmGlobalVisualStudio7Generator::Generate() this->OutputSLNFile(); } -// output the SLN file -void cmGlobalVisualStudio7Generator::OutputSLNFile() -{ - // if this is an out of source build, create the output directory - if(strcmp(m_CMakeInstance->GetStartOutputDirectory(), - m_CMakeInstance->GetHomeDirectory()) != 0) +void cmGlobalVisualStudio7Generator::OutputSLNFile(const char* projectName, + std::vector& generators) +{ + if(generators.size() == 0) { - if(!cmSystemTools::MakeDirectory(m_CMakeInstance->GetStartOutputDirectory())) - { - cmSystemTools::Error("Error creating output directory for SLN file", - m_CMakeInstance->GetStartOutputDirectory()); - } + return; } - // create the dsw file name - std::string fname; - fname = m_CMakeInstance->GetStartOutputDirectory(); + std::string fname = generators[0]->GetMakefile()->GetStartOutputDirectory(); fname += "/"; - if(strlen(m_LocalGenerators[0]->GetMakefile()->GetProjectName()) == 0) - { - m_LocalGenerators[0]->GetMakefile()->SetProjectName("Project"); - } - fname += m_LocalGenerators[0]->GetMakefile()->GetProjectName(); + fname += generators[0]->GetMakefile()->GetProjectName(); fname += ".sln"; std::ofstream fout(fname.c_str()); if(!fout) { - cmSystemTools::Error("Error can not open SLN file for write: " - ,fname.c_str()); + cmSystemTools::Error("Error can not open DSW file for write: ", + fname.c_str()); return; } - this->WriteSLNFile(fout); + this->WriteSLNFile(fout, generators); +} + +// output the SLN file +void cmGlobalVisualStudio7Generator::OutputSLNFile() +{ + std::map >::iterator it; + for(it = m_SubProjectMap.begin(); it!= m_SubProjectMap.end(); ++it) + { + std::vector& gen = it->second; + this->OutputSLNFile(it->first.c_str(), it->second); + } } // Write a SLN file to the stream -void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout) +void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout, + std::vector& generators) { // Write out the header for a SLN file this->WriteSLNHeader(fout); @@ -292,13 +312,15 @@ void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout) // Get the home directory with the trailing slash std::string homedir = m_CMakeInstance->GetHomeDirectory(); homedir += "/"; - + bool doneAllBuild = false; + bool doneRunTests = false; + // For each cmMakefile, create a VCProj for it, and // add it to this SLN file unsigned int i; - for(i = 0; i < m_LocalGenerators.size(); ++i) + for(i = 0; i < generators.size(); ++i) { - cmMakefile* mf = m_LocalGenerators[i]->GetMakefile(); + cmMakefile* mf = generators[i]->GetMakefile(); // Get the source directory from the makefile std::string dir = mf->GetStartDirectory(); @@ -310,28 +332,28 @@ void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout) // than one dsp could have been created per input CMakeLists.txt file // for each target std::vector dspnames = - static_cast(m_LocalGenerators[i]) + static_cast(generators[i]) ->GetCreatedProjectNames(); - cmTargets &tgts = m_LocalGenerators[i]->GetMakefile()->GetTargets(); + cmTargets &tgts = generators[i]->GetMakefile()->GetTargets(); cmTargets::iterator l = tgts.begin(); for(std::vector::iterator si = dspnames.begin(); l != tgts.end(); ++l) { // special handling for the current makefile - if(mf == m_LocalGenerators[0]->GetMakefile()) + if(mf == generators[0]->GetMakefile()) { dir = "."; // no subdirectory for project generated // if this is the special ALL_BUILD utility, then // make it depend on every other non UTILITY project. // This is done by adding the names to the GetUtilities // vector on the makefile - if(l->first == "ALL_BUILD") + if(l->first == "ALL_BUILD" && !doneAllBuild) { unsigned int j; - for(j = 0; j < m_LocalGenerators.size(); ++j) + for(j = 0; j < generators.size(); ++j) { const cmTargets &atgts = - m_LocalGenerators[j]->GetMakefile()->GetTargets(); + generators[j]->GetMakefile()->GetTargets(); for(cmTargets::const_iterator al = atgts.begin(); al != atgts.end(); ++al) { @@ -369,7 +391,33 @@ void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout) if ((l->second.GetType() != cmTarget::INSTALL_FILES) && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)) { - this->WriteProject(fout, si->c_str(), dir.c_str(),l->second); + bool skip = false; + if(l->first == "ALL_BUILD" ) + { + if(doneAllBuild) + { + skip = true; + } + else + { + doneAllBuild = true; + } + } + if(l->first == "RUN_TESTS") + { + if(doneRunTests) + { + skip = true; + } + else + { + doneRunTests = true; + } + } + if(!skip) + { + this->WriteProject(fout, si->c_str(), dir.c_str(),l->second); + } ++si; } } @@ -389,11 +437,11 @@ void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout) << "\tGlobalSection(ProjectDependencies) = postSolution\n"; // loop over again and compute the depends - for(i = 0; i < m_LocalGenerators.size(); ++i) + for(i = 0; i < generators.size(); ++i) { - cmMakefile* mf = m_LocalGenerators[i]->GetMakefile(); + cmMakefile* mf = generators[i]->GetMakefile(); cmLocalVisualStudio7Generator* pg = - static_cast(m_LocalGenerators[i]); + static_cast(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 @@ -416,11 +464,11 @@ void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout) fout << "\tEndGlobalSection\n"; fout << "\tGlobalSection(ProjectConfiguration) = postSolution\n"; // loop over again and compute the depends - for(i = 0; i < m_LocalGenerators.size(); ++i) + for(i = 0; i < generators.size(); ++i) { - cmMakefile* mf = m_LocalGenerators[i]->GetMakefile(); + cmMakefile* mf = generators[i]->GetMakefile(); cmLocalVisualStudio7Generator* pg = - static_cast(m_LocalGenerators[i]); + static_cast(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 @@ -603,3 +651,20 @@ void cmGlobalVisualStudio7Generator::GetDocumentation(cmDocumentationEntry& entr entry.brief = "Generates Visual Studio .NET 2002 project files."; entry.full = ""; } + +// populate the m_SubProjectMap +void cmGlobalVisualStudio7Generator::CollectSubprojects() +{ + unsigned int i; + for(i = 0; i < m_LocalGenerators.size(); ++i) + { + std::string name = m_LocalGenerators[i]->GetMakefile()->GetProjectName(); + m_SubProjectMap[name].push_back(m_LocalGenerators[i]); + std::vector const& pprojects + = m_LocalGenerators[i]->GetMakefile()->GetParentProjects(); + for(int k =0; k < pprojects.size(); ++k) + { + m_SubProjectMap[pprojects[k]].push_back(m_LocalGenerators[i]); + } + } +} diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index a268a44bd..a8e2fb1fa 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -82,7 +82,10 @@ public: std::vector *GetConfigurations(); protected: - virtual void WriteSLNFile(std::ostream& fout); + void CollectSubprojects(); + void OutputSLNFile(const char* projectName, + std::vector& generators); + virtual void WriteSLNFile(std::ostream& fout, std::vector& generators); virtual void WriteProject(std::ostream& fout, const char* name, const char* path, const cmTarget &t); @@ -103,6 +106,7 @@ protected: std::vector m_Configurations; std::map m_GUIDMap; + std::map > m_SubProjectMap; }; #endif diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index c1bb83332..348c48957 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -954,6 +954,10 @@ void cmMakefile::RemoveDefinition(const char* name) void cmMakefile::SetProjectName(const char* p) { + if(m_ProjectName.size()) + { + m_ParentProjects.push_back(m_ProjectName); + } m_ProjectName = p; } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 37678e795..28a5c3e5f 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -252,6 +252,10 @@ public: return m_ProjectName.c_str(); } + std::vector const& GetParentProjects() + { + return m_ParentProjects; + } /** * Set the name of the library. */ @@ -630,6 +634,7 @@ protected: std::string m_cmCurrentListFile; std::string m_ProjectName; // project name + std::vector m_ParentProjects; // libraries, classes, and executables cmTargets m_Targets;