diff options
author | Brad King <brad.king@kitware.com> | 2010-08-24 22:47:56 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2010-08-24 22:47:56 (GMT) |
commit | 79a88c35f886258a43ee6169d2d7b4f2e1eb0b95 (patch) | |
tree | c44185016a16e3fc10cc4c9dc8e6e874548adfcc | |
parent | 325bdb2a92bbbbe18ae2cbffc000bd6e0dd0367a (diff) | |
download | CMake-79a88c35f886258a43ee6169d2d7b4f2e1eb0b95.zip CMake-79a88c35f886258a43ee6169d2d7b4f2e1eb0b95.tar.gz CMake-79a88c35f886258a43ee6169d2d7b4f2e1eb0b95.tar.bz2 |
Refactor VS <= 7.1 utility-depends workaround
Commit 438a7e2f (Fix utility dependencies for static libraries in VS
generators, 2007-04-04) implemented utility-only dependencies between
linkable targets by introducing an intermediate non-linkable target.
We convert a dependency of the form
foo -> bar
to the form
foo -> bar_UTILITY -> bar
to prevent foo from including bar on its link line. Previously we added
the extra "_UTILITY" targets explicitly among the project targets before
dependency analysis was performed. Now we generate them separately at
the last moment so that cmGlobalGenerator need not be aware of them.
-rw-r--r-- | Source/cmGlobalVisualStudio6Generator.cxx | 61 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio6Generator.h | 1 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio71Generator.cxx | 19 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio7Generator.cxx | 74 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio7Generator.h | 1 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudioGenerator.cxx | 191 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudioGenerator.h | 14 |
7 files changed, 186 insertions, 175 deletions
diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index fa7afc5..203ca77 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -13,6 +13,7 @@ #include "cmLocalVisualStudio6Generator.h" #include "cmMakefile.h" #include "cmake.h" +#include "cmGeneratedFileStream.h" // Utility function to make a valid VS6 *.dsp filename out // of a CMake target name: @@ -284,6 +285,23 @@ void cmGlobalVisualStudio6Generator::WriteProject(std::ostream& fout, fout << "End Project Dependency\n"; } fout << "}}}\n\n"; + + UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target); + if(ui != this->UtilityDepends.end()) + { + const char* uname = ui->second.c_str(); + fout << "Project: \"" << uname << "\"=" + << dir << "\\" << uname << ".dsp - Package Owner=<4>\n\n"; + fout << + "Package=<5>\n{{{\n}}}\n\n" + "Package=<4>\n" + "{{{\n" + "Begin Project Dependency\n" + "Project_Dep_Name " << dspname << "\n" + "End Project Dependency\n" + "}}}\n\n"; + ; + } } @@ -340,6 +358,49 @@ void cmGlobalVisualStudio6Generator::WriteDSWHeader(std::ostream& fout) } //---------------------------------------------------------------------------- +std::string +cmGlobalVisualStudio6Generator::WriteUtilityDepend(cmTarget* target) +{ + std::string pname = target->GetName(); + pname += "_UTILITY"; + pname = GetVS6TargetName(pname.c_str()); + std::string fname = target->GetMakefile()->GetStartOutputDirectory(); + fname += "/"; + fname += pname; + fname += ".dsp"; + cmGeneratedFileStream fout(fname.c_str()); + fout.SetCopyIfDifferent(true); + fout << + "# Microsoft Developer Studio Project File - Name=\"" + << pname << "\" - Package Owner=<4>\n" + "# Microsoft Developer Studio Generated Build File, Format Version 6.00\n" + "# ** DO NOT EDIT **\n" + "\n" + "# TARGTYPE \"Win32 (x86) Generic Project\" 0x010a\n" + "\n" + "CFG=" << pname << " - Win32 Debug\n" + "!MESSAGE \"" << pname << " - Win32 Debug\"" + " (based on \"Win32 (x86) Generic Project\")\n" + "!MESSAGE \"" << pname << " - Win32 Release\" " + "(based on \"Win32 (x86) Generic Project\")\n" + "!MESSAGE \"" << pname << " - Win32 MinSizeRel\" " + "(based on \"Win32 (x86) Generic Project\")\n" + "!MESSAGE \"" << pname << " - Win32 RelWithDebInfo\" " + "(based on \"Win32 (x86) Generic Project\")\n" + "\n" + "# Begin Project\n" + "# Begin Target\n" + "# Name \"" << pname << " - Win32 Debug\"\n" + "# Name \"" << pname << " - Win32 Release\"\n" + "# Name \"" << pname << " - Win32 MinSizeRel\"\n" + "# Name \"" << pname << " - Win32 RelWithDebInfo\"\n" + "# End Target\n" + "# End Project\n" + ; + return pname; +} + +//---------------------------------------------------------------------------- void cmGlobalVisualStudio6Generator ::GetDocumentation(cmDocumentationEntry& entry) const { diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h index 553c7be..77d5370 100644 --- a/Source/cmGlobalVisualStudio6Generator.h +++ b/Source/cmGlobalVisualStudio6Generator.h @@ -96,6 +96,7 @@ private: const char* name, const char* path, const std::set<cmStdString>& dependencies); void WriteDSWFooter(std::ostream& fout); + virtual std::string WriteUtilityDepend(cmTarget* target); }; #endif diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index ac1bfa5..4f5901c 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -163,16 +163,31 @@ cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout, ext = targetExt; } + std::string guid = this->GetGUID(dspname); fout << project << dspname << "\", \"" << this->ConvertToSolutionPath(dir) - << "\\" << dspname << ext << "\", \"{" - << this->GetGUID(dspname) << "}\"\n"; + << "\\" << dspname << ext << "\", \"{" << guid << "}\"\n"; fout << "\tProjectSection(ProjectDependencies) = postProject\n"; this->WriteProjectDepends(fout, dspname, dir, t); fout << "\tEndProjectSection\n"; fout <<"EndProject\n"; + + UtilityDependsMap::iterator ui = this->UtilityDepends.find(&t); + if(ui != this->UtilityDepends.end()) + { + const char* uname = ui->second.c_str(); + fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"" + << uname << "\", \"" + << this->ConvertToSolutionPath(dir) + << "\\" << uname << ".vcproj" << "\", \"{" + << this->GetGUID(uname) << "}\"\n" + << "\tProjectSection(ProjectDependencies) = postProject\n" + << "\t\t{" << guid << "} = {" << guid << "}\n" + << "\tEndProjectSection\n" + << "EndProject\n"; + } } //---------------------------------------------------------------------------- diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index de88131..f59de40 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -408,6 +408,18 @@ void cmGlobalVisualStudio7Generator::WriteProject(std::ostream& fout, << this->ConvertToSolutionPath(dir) << "\\" << dspname << ext << "\", \"{" << this->GetGUID(dspname) << "}\"\nEndProject\n"; + + UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target); + if(ui != this->UtilityDepends.end()) + { + const char* uname = ui->second.c_str(); + fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"" + << uname << "\", \"" + << this->ConvertToSolutionPath(dir) + << "\\" << uname << ".vcproj" << "\", \"{" + << this->GetGUID(uname) << "}\"\n" + << "EndProject\n"; + } } @@ -440,6 +452,13 @@ cmGlobalVisualStudio7Generator fout << "\t\t{" << dspguid << "}." << depcount << " = {" << guid << "}\n"; depcount++; } + + UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target); + if(ui != this->UtilityDepends.end()) + { + const char* uname = ui->second.c_str(); + fout << "\t\t{" << this->GetGUID(uname) << "}.0 = {" << dspguid << "}\n"; + } } @@ -501,6 +520,61 @@ void cmGlobalVisualStudio7Generator::WriteSLNHeader(std::ostream& fout) fout << "Microsoft Visual Studio Solution File, Format Version 7.00\n"; } +//---------------------------------------------------------------------------- +std::string +cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget* target) +{ + std::string pname = target->GetName(); + pname += "_UTILITY"; + std::string fname = target->GetMakefile()->GetStartOutputDirectory(); + fname += "/"; + fname += pname; + fname += ".vcproj"; + cmGeneratedFileStream fout(fname.c_str()); + fout.SetCopyIfDifferent(true); + this->CreateGUID(pname.c_str()); + std::string guid = this->GetGUID(pname.c_str()); + + fout << + "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n" + "<VisualStudioProject\n" + "\tProjectType=\"Visual C++\"\n" + "\tVersion=\"" << this->GetIDEVersion() << "0\"\n" + "\tName=\"" << pname << "\"\n" + "\tProjectGUID=\"{" << guid << "}\"\n" + "\tKeyword=\"Win32Proj\">\n" + "\t<Platforms><Platform Name=\"Win32\"/></Platforms>\n" + "\t<Configurations>\n" + ; + for(std::vector<std::string>::iterator i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) + { + fout << + "\t\t<Configuration\n" + "\t\t\tName=\"" << *i << "|Win32\"\n" + "\t\t\tOutputDirectory=\"" << *i << "\"\n" + "\t\t\tIntermediateDirectory=\"" << pname << ".dir\\" << *i << "\"\n" + "\t\t\tConfigurationType=\"10\"\n" + "\t\t\tUseOfMFC=\"0\"\n" + "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"FALSE\"\n" + "\t\t\tCharacterSet=\"2\">\n" + "\t\t</Configuration>\n" + ; + } + fout << + "\t</Configurations>\n" + "\t<Files></Files>\n" + "\t<Globals></Globals>\n" + "</VisualStudioProject>\n" + ; + + if(fout.Close()) + { + this->FileReplacedDuringGenerate(fname); + } + return pname; +} + std::string cmGlobalVisualStudio7Generator::GetGUID(const char* name) { std::string guidStoreName = name; diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 85ba244..b89fa1c 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -113,6 +113,7 @@ protected: bool partOfDefaultBuild); virtual void WriteSLNFooter(std::ostream& fout); virtual void WriteSLNHeader(std::ostream& fout); + virtual std::string WriteUtilityDepend(cmTarget* target); virtual void AddPlatformDefinitions(cmMakefile* mf); virtual void WriteTargetsToSolution( diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 1007953..3493b1d 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -74,9 +74,6 @@ void cmGlobalVisualStudioGenerator::Generate() } } - // Fix utility dependencies to avoid linking to libraries. - this->FixUtilityDepends(); - // Configure CMake Visual Studio macros, for this user on this version // of Visual Studio. this->ConfigureCMakeVisualStudioMacros(); @@ -225,134 +222,6 @@ std::string cmGlobalVisualStudioGenerator::GetUserMacrosRegKeyBase() } //---------------------------------------------------------------------------- -void cmGlobalVisualStudioGenerator::FixUtilityDepends() -{ - // Skip for VS versions 8 and above. - if(!this->VSLinksDependencies()) - { - return; - } - - // For VS versions before 8: - // - // When a target that links contains a project-level dependency on a - // library target that library is automatically linked. In order to - // allow utility-style project-level dependencies that do not - // actually link we need to automatically insert an intermediate - // custom target. - // - // Here we edit the utility dependencies of a target to add the - // intermediate custom target when necessary. - for(unsigned i = 0; i < this->LocalGenerators.size(); ++i) - { - cmTargets* targets = - &(this->LocalGenerators[i]->GetMakefile()->GetTargets()); - for(cmTargets::iterator tarIt = targets->begin(); - tarIt != targets->end(); ++tarIt) - { - this->FixUtilityDependsForTarget(tarIt->second); - } - } -} - -//---------------------------------------------------------------------------- -void -cmGlobalVisualStudioGenerator::FixUtilityDependsForTarget(cmTarget& target) -{ - // Only targets that link need to be fixed. - if(target.GetType() != cmTarget::STATIC_LIBRARY && - target.GetType() != cmTarget::SHARED_LIBRARY && - target.GetType() != cmTarget::MODULE_LIBRARY && - target.GetType() != cmTarget::EXECUTABLE) - { - return; - } - -#if 0 - // This feature makes a mess in SLN files for VS 7.1 and below. It - // creates an extra target for every target that is "linked" by a - // static library. Without this feature static libraries do not - // wait until their "link" dependencies are built to build. This is - // not a problem 99.9% of the time, and projects that do have the - // problem can enable this work-around by using add_dependencies. - - // Static libraries cannot depend directly on the targets to which - // they link because VS will copy those targets into the library - // (for VS < 8). To work around the problem we copy the - // dependencies to be utility dependencies so that the work-around - // below is used. - if(target.GetType() == cmTarget::STATIC_LIBRARY) - { - cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries(); - for(cmTarget::LinkLibraryVectorType::const_iterator i = libs.begin(); - i != libs.end(); ++i) - { - if(cmTarget* depTarget = this->FindTarget(0, i->first.c_str(), false)) - { - target.AddUtility(depTarget->GetName()); - } - } - } -#endif - - // Look at each utility dependency. - for(std::set<cmStdString>::const_iterator ui = - target.GetUtilities().begin(); - ui != target.GetUtilities().end(); ++ui) - { - if(cmTarget* depTarget = this->FindTarget(0, ui->c_str())) - { - if(depTarget->GetType() == cmTarget::STATIC_LIBRARY || - depTarget->GetType() == cmTarget::SHARED_LIBRARY || - depTarget->GetType() == cmTarget::MODULE_LIBRARY) - { - // This utility dependency will cause an attempt to link. If - // the depender does not already link the dependee we need an - // intermediate target. - if(!this->CheckTargetLinks(target, ui->c_str())) - { - this->CreateUtilityDependTarget(*depTarget); - } - } - } - } -} - -//---------------------------------------------------------------------------- -void -cmGlobalVisualStudioGenerator::CreateUtilityDependTarget(cmTarget& target) -{ - // This target is a library on which a utility dependency exists. - // We need to create an intermediate custom target to hook up the - // dependency without causing a link. - const char* altName = target.GetProperty("ALTERNATIVE_DEPENDENCY_NAME"); - if(!altName) - { - // Create the intermediate utility target. - std::string altNameStr = target.GetName(); - altNameStr += "_UTILITY"; - const std::vector<std::string> no_depends; - cmCustomCommandLines no_commands; - const char* no_working_dir = 0; - const char* no_comment = 0; - target.GetMakefile()->AddUtilityCommand(altNameStr.c_str(), true, - no_working_dir, no_depends, - no_commands, false, no_comment); - target.SetProperty("ALTERNATIVE_DEPENDENCY_NAME", altNameStr.c_str()); - - // Most targets have a GUID created in ConfigureFinalPass. Since - // that has already been called, create one for this target now. - this->CreateGUID(altNameStr.c_str()); - - // The intermediate target should depend on the original target. - if(cmTarget* alt = this->FindTarget(0, altNameStr.c_str())) - { - alt->AddUtility(target.GetName()); - } - } -} - -//---------------------------------------------------------------------------- bool cmGlobalVisualStudioGenerator::ComputeTargetDepends() { if(!this->cmGlobalGenerator::ComputeTargetDepends()) @@ -433,10 +302,28 @@ bool cmGlobalVisualStudioGenerator::CheckTargetLinks(cmTarget& target, } //---------------------------------------------------------------------------- -const char* +std::string cmGlobalVisualStudioGenerator::GetUtilityDepend(cmTarget* target) +{ + UtilityDependsMap::iterator i = this->UtilityDepends.find(target); + if(i == this->UtilityDepends.end()) + { + std::string name = this->WriteUtilityDepend(target); + UtilityDependsMap::value_type entry(target, name); + i = this->UtilityDepends.insert(entry).first; + } + return i->second; +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target, const char* name) { + if(!this->VSLinksDependencies()) + { + return name; + } + // Possibly depend on an intermediate utility target to avoid // linking. if(target.GetType() == cmTarget::STATIC_LIBRARY || @@ -444,19 +331,19 @@ cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target, target.GetType() == cmTarget::MODULE_LIBRARY || target.GetType() == cmTarget::EXECUTABLE) { - // The depender is a target that links. Lookup the dependee to - // see if it provides an alternative dependency name. + // The depender is a target that links. if(cmTarget* depTarget = this->FindTarget(0, name)) { - // Check for an alternative name created by FixUtilityDepends. - if(const char* altName = - depTarget->GetProperty("ALTERNATIVE_DEPENDENCY_NAME")) + if(depTarget->GetType() == cmTarget::STATIC_LIBRARY || + depTarget->GetType() == cmTarget::SHARED_LIBRARY || + depTarget->GetType() == cmTarget::MODULE_LIBRARY) { - // The alternative name is needed only if the depender does - // not really link to the dependee. + // This utility dependency will cause an attempt to link. If + // the depender does not already link the dependee we need an + // intermediate target. if(!this->CheckTargetLinks(target, name)) { - return altName; + return this->GetUtilityDepend(depTarget); } } } @@ -467,30 +354,6 @@ cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target, } //---------------------------------------------------------------------------- -void cmGlobalVisualStudioGenerator::GetTargetSets( - TargetDependSet& projectTargets, TargetDependSet& originalTargets, - cmLocalGenerator* root, GeneratorVector const& generators - ) -{ - this->cmGlobalGenerator::GetTargetSets(projectTargets, originalTargets, - root, generators); - - // Add alternative dependency targets created by FixUtilityDepends. - for(TargetDependSet::iterator ti = projectTargets.begin(); - ti != projectTargets.end(); ++ti) - { - cmTarget* tgt = *ti; - if(const char* altName = tgt->GetProperty("ALTERNATIVE_DEPENDENCY_NAME")) - { - if(cmTarget* alt = tgt->GetMakefile()->FindTarget(altName)) - { - projectTargets.insert(alt); - } - } - } -} - -//---------------------------------------------------------------------------- #include <windows.h> //---------------------------------------------------------------------------- diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 3d499e3..daa6b3a 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -61,7 +61,6 @@ public: // return true if target is fortran only bool TargetIsFortranOnly(cmTarget& t); - const char* GetUtilityForTarget(cmTarget& target, const char*); /** Get the top-level registry key for this VS version. */ std::string GetRegistryBase(); @@ -71,8 +70,6 @@ public: virtual bool IsMultiConfig() { return true; } protected: - void FixUtilityDepends(); - // Does this VS version link targets to each other if there are // dependencies in the SLN file? This was done for VS versions // below 8. @@ -90,9 +87,6 @@ protected: OrderedTargetDependSet(cmGlobalGenerator::TargetDependSet const&); }; - virtual void GetTargetSets(TargetDependSet& projectTargets, - TargetDependSet& originalTargets, - cmLocalGenerator* root, GeneratorVector const&); virtual bool ComputeTargetDepends(); class VSDependSet: public std::set<cmStdString> {}; class VSDependMap: public std::map<cmTarget*, VSDependSet> {}; @@ -100,9 +94,11 @@ protected: void ComputeVSTargetDepends(cmTarget&); bool CheckTargetLinks(cmTarget& target, const char* name); -private: - void FixUtilityDependsForTarget(cmTarget& target); - void CreateUtilityDependTarget(cmTarget& target); + std::string GetUtilityForTarget(cmTarget& target, const char*); + virtual std::string WriteUtilityDepend(cmTarget*) = 0; + std::string GetUtilityDepend(cmTarget* target); + typedef std::map<cmTarget*, cmStdString> UtilityDependsMap; + UtilityDependsMap UtilityDepends; }; #endif |