View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0003218CMakeCMakepublic2006-05-11 02:322008-02-06 10:12
ReporterManuel Klimek 
Assigned ToBill Hoffman 
PrioritynormalSeverityfeatureReproducibilityalways
StatusclosedResolutionfixed 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0003218: Automatic Visual Studio dependency generation (patch)
DescriptionThe visual studio sln generator should write dependant projects from the same cmake tree automatically.

--- cmake-2.4.1-orig/Source/cmGlobalVisualStudio71Generator.cxx 2006-04-30 17:06:37.000000000 +0200
+++ cmake-2.4.1/Source/cmGlobalVisualStudio71Generator.cxx 2006-05-10 13:36:19.343750000 +0200
@@ -44,7 +44,7 @@
 // Write a SLN file to the stream
 void cmGlobalVisualStudio71Generator::WriteSLNFile(std::ostream& fout,
                                                    cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators)
+ std::vector<cmLocalGenerator*>& localGenerators)
 {
   // Write out the header for a SLN file
   this->WriteSLNHeader(fout);
@@ -59,7 +59,71 @@
   bool doneEditCache = false;
   bool doneRebuildCache = false;
   bool donePackage = false;
-
+
+ std::vector<cmLocalGenerator*> generators = localGenerators;
+ if(!generators.empty())
+ {
+ // calculate closure on library dependencies
+ cmLocalGenerator *topGenerator = generators[0];
+ while(topGenerator->GetParent() != NULL)
+ {
+ topGenerator = topGenerator->GetParent();
+ }
+ unsigned int lastSize = 0;
+ do
+ {
+ std::vector<cmLocalGenerator*> dependencyGenerators;
+ lastSize = generators.size();
+ // build closure
+ for(unsigned int i=0; i<generators.size(); ++i)
+ {
+ cmMakefile *makefile = generators[i]->GetMakefile();
+ for(cmTargets::iterator it=makefile->GetTargets().begin(); it != makefile->GetTargets().end(); ++it)
+ {
+ if(it->second.GetType() != cmTarget::STATIC_LIBRARY)
+ {
+ cmTarget::LinkLibraryVectorType::const_iterator j, jend;
+ j = it->second.GetLinkLibraries().begin();
+ jend = it->second.GetLinkLibraries().end();
+ for(;j!= jend; ++j)
+ {
+ cmTarget *dependency = topGenerator->GetGlobalGenerator()->FindTarget(NULL, j->first.c_str());
+ if(dependency)
+ {
+ cmLocalGenerator* generator = topGenerator->GetGlobalGenerator()->FindLocalGenerator(dependency->GetMakefile()->GetCurrentDirectory());
+ bool found = false;
+ for(unsigned int k=0; k<generators.size() && !found; ++k)
+ {
+ if(generators[k] == generator)
+ {
+ found = true;
+ }
+ }
+ for(unsigned int k=0; k<dependencyGenerators.size() && !found; ++k)
+ {
+ if(dependencyGenerators[k] == generator)
+ {
+ found = true;
+ }
+ }
+ if(!found)
+ {
+ dependencyGenerators.push_back(generator);
+ this->ProjectMap[generators[i]->GetMakefile()->GetProjectName()].push_back(generator);
+ }
+ }
+ }
+ }
+ }
+ }
+ for(unsigned int i=0; i<dependencyGenerators.size(); ++i)
+ {
+ generators.push_back(dependencyGenerators[i]);
+ }
+ }
+ while(lastSize < generators.size());
+ }
+
   // For each cmMakefile, create a VCProj for it, and
   // add it to this SLN file
   unsigned int i;
TagsNo tags attached.
Attached Files? file icon patch [^] (8,549 bytes) 2007-08-09 08:48 [Show Content]

 Relationships

  Notes
(0004392)
Manuel Klimek (reporter)
2006-07-03 02:04

New patch: works for me quite well ;-)

Index: cmGlobalVisualStudio71Generator.cxx
===================================================================
--- cmGlobalVisualStudio71Generator.cxx (.../tags/cmake-2.4.2/Source/cmGlobalVisualStudio71Generator.cxx) (revision 16548)
+++ cmGlobalVisualStudio71Generator.cxx (.../trunk/cmake/Source/cmGlobalVisualStudio71Generator.cxx) (revision 16548)
@@ -48,7 +48,7 @@
 void cmGlobalVisualStudio71Generator
 ::WriteSLNFile(std::ostream& fout,
                                                    cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators)
+ std::vector<cmLocalGenerator*>& localGenerators)
 {
   // Write out the header for a SLN file
   this->WriteSLNHeader(fout);
@@ -64,6 +64,150 @@
   bool doneRebuildCache = false;
   bool donePackage = false;
   
+ std::vector<cmLocalGenerator*> generators = localGenerators;
+ if(!generators.empty())
+ {
+ // initialize used targets
+ // for every generator we'll store all targets in this
+ // generator we depend on
+ // we start by adding all targets in the generators we got
+ // as parameter to this method:
+ // (this adds cmake standard targets like INSTALL and ZERO_CHECK etc,
+ // too, which is used later to prevent totally unrelated projects
+ // from getting linked in by FindTarget with a standard target as
+ // argument)
+ std::vector< std::vector<cmTarget*> > usedTargets(generators.size());
+ for(unsigned int i=0; i<generators.size(); ++i)
+ {
+ cmMakefile *makefile = generators[i]->GetMakefile();
+ // add all targets to our "used target matrix"
+ for(cmTargets::iterator it=makefile->GetTargets().begin(); it !=
+ makefile->GetTargets().end(); ++it)
+ {
+ usedTargets[i].push_back(&it->second);
+ }
+ }
+
+ // calculate closure on library dependencies
+ // let's get the top generator; we need it to find
+ // targets anywhere in the tree if we're in a subdirectory
+ cmLocalGenerator *topGenerator = generators[0];
+ while(topGenerator->GetParent() != NULL)
+ {
+ topGenerator = topGenerator->GetParent();
+ }
+ // algorithm:
+ // for each target in the "used target matrix":
+ // find all dependent targets:
+ // if any new target is found, add it to the "used target matrix"
+ // loop until no new dependencies are found
+ bool changed = false;
+ do
+ {
+ changed = false;
+ // build closure
+ unsigned int generatorSize = generators.size();
+ for(unsigned int iGenerator=0; iGenerator<generatorSize; ++iGenerator)
+ {
+ for(unsigned int iTarget=0; iTarget<usedTargets[iGenerator].size(); ++iTarget)
+ {
+ // find all targets this target depends on;
+ // use link libraries as well as utilities (for example
+ // executables that are needed for the build process)
+ std::vector<std::string> targetDependencies;
+ {
+ cmTarget::LinkLibraryVectorType::const_iterator j, jend;
+ j = usedTargets[iGenerator][iTarget]->GetLinkLibraries().begin();
+ jend = usedTargets[iGenerator][iTarget]->GetLinkLibraries().end();
+ for(;j!= jend; ++j)
+ {
+ targetDependencies.push_back(j->first);
+ }
+ }
+ {
+ std::set<cmStdString>::const_iterator j, jend;
+ j = usedTargets[iGenerator][iTarget]->GetUtilities().begin();
+ jend = usedTargets[iGenerator][iTarget]->GetUtilities().end();
+ for(;j!= jend; ++j)
+ {
+ targetDependencies.push_back(*j);
+ }
+ }
+ // for each target we depend on, check if this target is
+ // already in our "used target matrix"
+ for(unsigned int iDependency=0; iDependency<targetDependencies.size();
+ ++iDependency)
+ {
+ bool foundTarget = false;
+ for(unsigned int gen=0; gen<usedTargets.size(); ++gen)
+ {
+ for(unsigned int k=0; k<usedTargets[gen].size() &&
+ !foundTarget; ++k)
+ {
+ if(usedTargets[gen][k]->GetName() == targetDependencies[iDependency])
+ {
+ foundTarget = true;
+ }
+ }
+ }
+ // if it's not in our "used target matrix", enter it:
+ if(!foundTarget)
+ {
+ // find the target globally (as far as I understand,
+ // cmake doesn't support multiple targets with the
+ // same name in subdirectories, with the exception
+ // of some standard cmake targets (INSTALL, ZERO_CHECK ...)
+ // so FindTarget should always return one exact match;
+ cmTarget *dependency =
+ topGenerator->GetGlobalGenerator()->
+ FindTarget(NULL,targetDependencies[iDependency].c_str());
+ if(dependency)
+ {
+ // do we have to add the whole generator? Yes, since
+ // we just want to include the project files where the
+ // targets are built in our workspace
+ // but we'll only add the dependencies for the targets
+ // that depend on our main target
+ cmLocalGenerator* generator =
+ dependency->GetMakefile()->GetLocalGenerator();
+ // let's see if we already have this generator
+ // perhaps we should do string comparison, not
+ // pointer comparison?
+ int entryGenerator = -1;
+ for(unsigned int k=0; k<generators.size() &&
+ (entryGenerator == -1); ++k)
+ {
+ if(generators[k] == generator)
+ {
+ entryGenerator = k;
+ }
+ }
+ // if we don't find the generator the new target is
+ // in, we add the generator
+ if(entryGenerator == -1)
+ {
+ // we have to update the project map - if we don't
+ // the target dependencies will not be written
+ this->ProjectMap[generators[iGenerator]->
+ GetMakefile()->GetProjectName()].push_back(generator);
+ entryGenerator = generators.size();
+ generators.push_back(generator);
+ usedTargets.push_back(std::vector<cmTarget*>());
+ }
+ // we know that this is a new target, otherwise we
+ // wouldn't end here - so just add the new target
+ usedTargets[entryGenerator].push_back(dependency);
+ // run again over the new "used target matrix"
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ while(changed);
+ }
+
   // For each cmMakefile, create a VCProj for it, and
   // add it to this SLN file
   unsigned int i;
@@ -294,10 +438,17 @@
                                               const char* dir,
                                               cmTarget& t)
 {
- std::string d = cmSystemTools::ConvertToOutputPath(dir);
+ std::string d = dir;
+ d += "/";
+ d += dspname;
+ d += ".vcproj";
+ d = cmSystemTools::ConvertToOutputPath(d.c_str());
+ if(d[0] != '\"')
+ {
+ d = std::string("\"") + d + std::string("\"");
+ }
   fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
- << dspname << "\", \""
- << d << "\\" << dspname << ".vcproj\", \"{"
+ << dspname << "\", " << d << " ,\"{"
        << this->GetGUID(dspname) << "}\"\n";
   fout << "\tProjectSection(ProjectDependencies) = postProject\n";
   this->WriteProjectDepends(fout, dspname, dir, t);
(0006578)
Manuel Klimek (reporter)
2007-02-28 02:31

If you need an up to date patch or to resolve some issues to get this into the main line, please let me know, I'm willing to help ...

Manuel
(0007710)
Manuel Klimek (reporter)
2007-05-22 06:38

An additional fix for target dependency generation in subdir sln files...

Index: E:/proj/cmake/Source/cmGlobalVisualStudio71Generator.cxx
===================================================================
--- E:/proj/cmake/Source/cmGlobalVisualStudio71Generator.cxx (revision 24706)
+++ E:/proj/cmake/Source/cmGlobalVisualStudio71Generator.cxx (working copy)
@@ -188,7 +188,9 @@
                   {
                   // we have to update the project map - if we don't
                   // the target dependencies will not be written
- this->ProjectMap[generators[iGenerator]->
+ // we must use the current generator (generators[0]),
+ // since this will be used when writing the dependencies
+ this->ProjectMap[generators[0]->
                     GetMakefile()->GetProjectName()].push_back(generator);
                   entryGenerator = generators.size();
                   generators.push_back(generator);
(0008385)
Torsten Martinsen (reporter)
2007-08-09 08:48

Attached updated patch for CMake 2.4.7.
(0010385)
Bill Hoffman (manager)
2008-02-06 10:12

This should be fixed in CVS CMake now. Please try, as this implementation will go in 2.6 beta.

 Issue History
Date Modified Username Field Change
2007-08-09 08:48 Torsten Martinsen File Added: patch
2007-08-09 08:48 Torsten Martinsen Note Added: 0008385
2007-08-30 10:32 Mathieu Malaterre Assigned To System Admin =>
2007-08-30 10:33 Mathieu Malaterre Assigned To => Alex Neundorf
2007-08-30 10:48 Alex Neundorf Assigned To Alex Neundorf => Bill Hoffman
2008-02-06 10:12 Bill Hoffman Status assigned => closed
2008-02-06 10:12 Bill Hoffman Note Added: 0010385
2008-02-06 10:12 Bill Hoffman Resolution open => fixed


Copyright © 2000 - 2018 MantisBT Team