diff options
author | Brad King <brad.king@kitware.com> | 2007-04-04 18:50:35 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2007-04-04 18:50:35 (GMT) |
commit | 438a7e2fcef6c82dd93e0106208dbaee7e9ccfc4 (patch) | |
tree | 457a6595797e62866b70c4d7e6b4f428b7da033b /Source/cmGlobalVisualStudioGenerator.cxx | |
parent | 2803688998cebbd40df1a0678106e62271217add (diff) | |
download | CMake-438a7e2fcef6c82dd93e0106208dbaee7e9ccfc4.zip CMake-438a7e2fcef6c82dd93e0106208dbaee7e9ccfc4.tar.gz CMake-438a7e2fcef6c82dd93e0106208dbaee7e9ccfc4.tar.bz2 |
BUG: Fix utility dependencies for static libraries in VS generators. This addresses bug#4789.
Diffstat (limited to 'Source/cmGlobalVisualStudioGenerator.cxx')
-rw-r--r-- | Source/cmGlobalVisualStudioGenerator.cxx | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 8a7c4ff..46ce76e 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -16,6 +16,10 @@ =========================================================================*/ #include "cmGlobalVisualStudioGenerator.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmTarget.h" + //---------------------------------------------------------------------------- cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator() { @@ -25,3 +29,167 @@ cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator() cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator() { } + +//---------------------------------------------------------------------------- +void cmGlobalVisualStudioGenerator::FixUtilityDepends() +{ + // 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; + } + + // 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::CheckTargetLinks(cmTarget& target, + const char* name) +{ + // Return whether the given target links to a target with the given name. + if(target.GetType() == cmTarget::STATIC_LIBRARY) + { + // Static libraries never link to anything. + return false; + } + cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries(); + for(cmTarget::LinkLibraryVectorType::const_iterator i = libs.begin(); + i != libs.end(); ++i) + { + if(i->first == name) + { + return true; + } + } + return false; +} + +//---------------------------------------------------------------------------- +const char* +cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target, + const char* name) +{ + // Handle the external MS project special case. + if(strncmp(name, "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0) + { + // Note from Ken: + // kind of weird removing the first 27 letters. my + // recommendatsions: use cmCustomCommand::GetCommand() to get the + // project name or get rid of the target name starting with + // "INCLUDE_EXTERNAL_MSPROJECT_" and use another indicator/flag + // somewhere. These external project names shouldn't conflict + // with cmake target names anyways. + return name+27; + } + + // Possibly depend on an intermediate utility target to avoid + // linking. + if(target.GetType() == cmTarget::STATIC_LIBRARY || + target.GetType() == cmTarget::SHARED_LIBRARY || + 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. + if(cmTarget* depTarget = this->FindTarget(0, name)) + { + // Check for an alternative name created by FixUtilityDepends. + if(const char* altName = + depTarget->GetProperty("ALTERNATIVE_DEPENDENCY_NAME")) + { + // The alternative name is needed only if the depender does + // not really link to the dependee. + if(!this->CheckTargetLinks(target, name)) + { + return altName; + } + } + } + } + + // No special case. Just use the original dependency name. + return name; +} |