ENH: Make static library targets depend on targets to which they "link" for the purpose of build ordering. This makes the build order consistent for static and shared library builds. It is also useful when custom command inputs of one library are generated as custom commands outputs of another. It may be useful in the future for Fortran module dependencies. Implemented for Makefiles, Xcode, and VS 8 and above. Added sample code to do it for VS 7.1 and below, but left it disabled with comments explaining why. Likely it will never be needed on VS 7.1 or below anyway.

This commit is contained in:
Brad King 2007-12-21 15:04:06 -05:00
parent d2be142e3b
commit 3cf3bb664a
6 changed files with 80 additions and 59 deletions

View File

@ -903,24 +903,21 @@ cmGlobalUnixMakefileGenerator3
// A target should not depend on itself.
emitted.insert(target.GetName());
// Loop over all library dependencies but not for static libs
if (target.GetType() != cmTarget::STATIC_LIBRARY)
// Loop over all library dependencies.
const cmTarget::LinkLibraryVectorType& tlibs = target.GetLinkLibraries();
for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
lib != tlibs.end(); ++lib)
{
const cmTarget::LinkLibraryVectorType& tlibs = target.GetLinkLibraries();
for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
lib != tlibs.end(); ++lib)
// Don't emit the same library twice for this target.
if(emitted.insert(lib->first).second)
{
// Don't emit the same library twice for this target.
if(emitted.insert(lib->first).second)
{
// Add this dependency.
this->AppendAnyGlobalDepend(depends, lib->first.c_str(),
emitted, target);
}
// Add this dependency.
this->AppendAnyGlobalDepend(depends, lib->first.c_str(),
emitted, target);
}
}
// Loop over all utility dependencies.
const std::set<cmStdString>& tutils = target.GetUtilities();
for(std::set<cmStdString>::const_iterator util = tutils.begin();
@ -967,24 +964,6 @@ cmGlobalUnixMakefileGenerator3
std::string tgtName = lg3->GetRelativeTargetDirectory(*result);
tgtName += "/all";
depends.push_back(tgtName);
if(result->GetType() == cmTarget::STATIC_LIBRARY)
{
// Since the static library itself does not list dependencies we
// need to chain its dependencies here.
const cmTarget::LinkLibraryVectorType& tlibs
= result->GetLinkLibraries();
for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
lib != tlibs.end(); ++lib)
{
// Don't emit the same library twice for this target.
if(emitted.insert(lib->first).second)
{
// Add this dependency.
this->AppendAnyGlobalDepend(depends, lib->first.c_str(),
emitted, *result);
}
}
}
return;
}
}

View File

@ -317,8 +317,14 @@ cmGlobalVisualStudio71Generator
const char* dspname,
const char*, cmTarget& target)
{
// insert Begin Project Dependency Project_Dep_Name project stuff here
if (target.GetType() != cmTarget::STATIC_LIBRARY)
// Create inter-target dependencies in the solution file. For VS
// 7.1 and below we cannot let static libraries depend directly on
// targets to which they "link" because the librarian tool will copy
// the targets into the static library. See
// cmGlobalVisualStudioGenerator::FixUtilityDependsForTarget for a
// work-around. VS 8 and above do not have this problem.
if (!this->VSLinksDependencies() ||
target.GetType() != cmTarget::STATIC_LIBRARY)
{
cmTarget::LinkLibraryVectorType::const_iterator j, jend;
j = target.GetLinkLibraries().begin();

View File

@ -59,8 +59,7 @@ public:
protected:
// Utility target fix is not needed for VS8.
virtual void FixUtilityDepends() {}
virtual bool VSLinksDependencies() const { return false; }
static cmVS7FlagTable const* GetExtraFlagTableVS8();
virtual void AddPlatformDefinitions(cmMakefile* mf);

View File

@ -197,6 +197,12 @@ std::string cmGlobalVisualStudioGenerator::GetUserMacrosDirectory()
//----------------------------------------------------------------------------
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
@ -232,6 +238,33 @@ cmGlobalVisualStudioGenerator::FixUtilityDependsForTarget(cmTarget& target)
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();

View File

@ -60,9 +60,14 @@ public:
protected:
virtual void CreateGUID(const char*) {}
virtual void FixUtilityDepends();
void FixUtilityDepends();
const char* GetUtilityForTarget(cmTarget& target, const char*);
// 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.
virtual bool VSLinksDependencies() const { return true; }
private:
void FixUtilityDependsForTarget(cmTarget& target);
void CreateUtilityDependTarget(cmTarget& target);

View File

@ -2006,34 +2006,33 @@ void cmGlobalXCodeGenerator
}
// Add dependencies on other CMake targets.
if(cmtarget->GetType() != cmTarget::STATIC_LIBRARY)
{
// Keep track of dependencies already listed.
std::set<cmStdString> emitted;
// A target should not depend on itself.
emitted.insert(cmtarget->GetName());
// Loop over all library dependencies.
const cmTarget::LinkLibraryVectorType& tlibs =
cmtarget->GetLinkLibraries();
for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
lib != tlibs.end(); ++lib)
{
// Keep track of dependencies already listed.
std::set<cmStdString> emitted;
// A target should not depend on itself.
emitted.insert(cmtarget->GetName());
// Loop over all library dependencies.
const cmTarget::LinkLibraryVectorType& tlibs =
cmtarget->GetLinkLibraries();
for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
lib != tlibs.end(); ++lib)
// Don't emit the same library twice for this target.
if(emitted.insert(lib->first).second)
{
// Don't emit the same library twice for this target.
if(emitted.insert(lib->first).second)
// Add this dependency.
cmTarget* t = this->FindTarget(this->CurrentProject.c_str(),
lib->first.c_str(), false);
cmXCodeObject* dptarget = this->FindXCodeTarget(t);
if(dptarget)
{
// Add this dependency.
cmTarget* t = this->FindTarget(this->CurrentProject.c_str(),
lib->first.c_str(), false);
cmXCodeObject* dptarget = this->FindXCodeTarget(t);
if(dptarget)
{
this->AddDependTarget(target, dptarget);
}
this->AddDependTarget(target, dptarget);
}
}
}
}
// write utility dependencies.
for(std::set<cmStdString>::const_iterator i