summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2010-08-24 22:47:56 (GMT)
committerBrad King <brad.king@kitware.com>2010-08-24 22:47:56 (GMT)
commit79a88c35f886258a43ee6169d2d7b4f2e1eb0b95 (patch)
treec44185016a16e3fc10cc4c9dc8e6e874548adfcc
parent325bdb2a92bbbbe18ae2cbffc000bd6e0dd0367a (diff)
downloadCMake-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.cxx61
-rw-r--r--Source/cmGlobalVisualStudio6Generator.h1
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx19
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx74
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h1
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx191
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h14
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