View Issue Details [ Jump to Notes ] | [ Print ] | ||||||||
ID | Project | Category | View Status | Date Submitted | Last Update | ||||
0003218 | CMake | CMake | public | 2006-05-11 02:32 | 2008-02-06 10:12 | ||||
Reporter | Manuel Klimek | ||||||||
Assigned To | Bill Hoffman | ||||||||
Priority | normal | Severity | feature | Reproducibility | always | ||||
Status | closed | Resolution | fixed | ||||||
Platform | OS | OS Version | |||||||
Product Version | |||||||||
Target Version | Fixed in Version | ||||||||
Summary | 0003218: Automatic Visual Studio dependency generation (patch) | ||||||||
Description | The 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; | ||||||||
Tags | No tags attached. | ||||||||
Attached Files | patch [^] (8,549 bytes) 2007-08-09 08:48 [Show Content] | ||||||||
Relationships | |
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. |
Notes |
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 |
Issue History |
Copyright © 2000 - 2018 MantisBT Team |