cd c:/user/tma/cmake-2.4.7/Source/ diff -bu "c:/user/tma/cmake-2.4.7/Source.orig/" "c:/user/tma/cmake-2.4.7/Source/" diff -bu c:/user/tma/cmake-2.4.7/Source.orig/cmGlobalVisualStudio71Generator.cxx c:/user/tma/cmake-2.4.7/Source/cmGlobalVisualStudio71Generator.cxx --- c:/user/tma/cmake-2.4.7/Source.orig/cmGlobalVisualStudio71Generator.cxx Mon Jul 16 17:16:42 2007 +++ c:/user/tma/cmake-2.4.7/Source/cmGlobalVisualStudio71Generator.cxx Fri Jul 27 11:21:39 2007 @@ -49,7 +49,7 @@ void cmGlobalVisualStudio71Generator ::WriteSLNFile(std::ostream& fout, cmLocalGenerator* root, - std::vector& generators) + std::vector& localGenerators) { // Write out the header for a SLN file this->WriteSLNHeader(fout); @@ -65,7 +65,153 @@ bool doneRebuildCache = false; bool donePackage = false; - // For each cmMakefile, create a VCProj for it, and + std::vector 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 > usedTargets(generators.size()); + for(unsigned int i=0; iGetMakefile(); + // 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 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::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; iDependencyGetName() == 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; kProjectMap[generators[0]-> + GetMakefile()->GetProjectName()].push_back(generator); + entryGenerator = generators.size(); + generators.push_back(generator); + usedTargets.push_back(std::vector()); + } + // 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; for(i = 0; i < generators.size(); ++i) @@ -298,10 +444,17 @@ const char* dir, cmTarget& t) { + 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 << "\", \"" - << this->ConvertToSolutionPath(dir) - << "\\" << dspname << ".vcproj\", \"{" + << dspname << "\", " << d << " ,\"{" << this->GetGUID(dspname) << "}\"\n"; fout << "\tProjectSection(ProjectDependencies) = postProject\n"; this->WriteProjectDepends(fout, dspname, dir, t);