From 40fc9174e21b8671dcac6545d0af1e5c6df55ee6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 7 Aug 2008 17:51:29 -0400 Subject: [PATCH] ENH: Tolerate repeated link library types The "debug", "optimized", and "general" link library type specifier arguments to the target_link_library commands are sometimes repeated in user code due to variable expansion and other complications. Instead of silently accepting the duplicates and trying to link to a bogus library like "optimized.lib", warn and ignore the earlier specifiers. --- Source/cmTargetLinkLibrariesCommand.cxx | 86 +++++++++++++++++-------- Source/cmTargetLinkLibrariesCommand.h | 2 + 2 files changed, 62 insertions(+), 26 deletions(-) diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 8c06e071e..73bb5a5b3 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -16,6 +16,13 @@ =========================================================================*/ #include "cmTargetLinkLibrariesCommand.h" +const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] = +{ + "general", + "debug", + "optimized" +}; + // cmTargetLinkLibrariesCommand bool cmTargetLinkLibrariesCommand ::InitialPass(std::vector const& args, cmExecutionStatus &) @@ -32,57 +39,60 @@ bool cmTargetLinkLibrariesCommand { return true; } + + // Keep track of link configuration specifiers. + cmTarget::LinkLibraryType llt = cmTarget::GENERAL; + bool haveLLT = false; + // add libraries, nothe that there is an optional prefix // of debug and optimized than can be used std::vector::const_iterator i = args.begin(); for(++i; i != args.end(); ++i) { - if (*i == "debug") + if(*i == "debug") { - ++i; - if(i == args.end()) + if(haveLLT) { - this->SetError - ("The \"debug\" argument must be followed by a library"); - return false; + this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::DEBUG); } - this->Makefile->AddLinkLibraryForTarget(args[0].c_str(),i->c_str(), - cmTarget::DEBUG); + llt = cmTarget::DEBUG; + haveLLT = true; } - else if (*i == "optimized") + else if(*i == "optimized") { - ++i; - if(i == args.end()) + if(haveLLT) { - this->SetError( - "The \"optimized\" argument must be followed by a library"); - return false; + this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::OPTIMIZED); } - this->Makefile->AddLinkLibraryForTarget(args[0].c_str(),i->c_str(), - cmTarget::OPTIMIZED); + llt = cmTarget::OPTIMIZED; + haveLLT = true; } - else if (*i == "general") + else if(*i == "general") { - ++i; - if(i == args.end()) + if(haveLLT) { - this->SetError( - "The \"general\" argument must be followed by a library"); - return false; + this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::GENERAL); } - this->Makefile->AddLinkLibraryForTarget(args[0].c_str(),i->c_str(), - cmTarget::GENERAL); + llt = cmTarget::GENERAL; + haveLLT = true; + } + else if(haveLLT) + { + // The link type was specified by the previous argument. + haveLLT = false; + this->Makefile->AddLinkLibraryForTarget(args[0].c_str(), + i->c_str(), llt); } else { - // make sure the type is correct if it is currently general. So if you + // Lookup old-style cache entry if type is unspecified. So if you // do a target_link_libraries(foo optimized bar) it will stay optimized // and not use the lookup. As there maybe the case where someone has // specifed that a library is both debug and optimized. (this check is // only there for backwards compatibility when mixing projects built // with old versions of CMake and new) - cmTarget::LinkLibraryType llt = cmTarget::GENERAL; + llt = cmTarget::GENERAL; std::string linkType = args[0]; linkType += "_LINK_TYPE"; const char* linkTypeString = @@ -101,5 +111,29 @@ bool cmTargetLinkLibrariesCommand this->Makefile->AddLinkLibraryForTarget(args[0].c_str(),i->c_str(),llt); } } + + // Make sure the last argument was not a library type specifier. + if(haveLLT) + { + cmOStringStream e; + e << "The \"" << this->LinkLibraryTypeNames[llt] + << "\" argument must be followed by a library."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + } + return true; } + +//---------------------------------------------------------------------------- +void +cmTargetLinkLibrariesCommand +::LinkLibraryTypeSpecifierWarning(int left, int right) +{ + cmOStringStream w; + w << "Link library type specifier \"" + << this->LinkLibraryTypeNames[left] << "\" is followed by specifier \"" + << this->LinkLibraryTypeNames[right] << "\" instead of a library name. " + << "The first specifier will be ignored."; + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); +} diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index de20533cb..ccf86ad80 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -79,6 +79,8 @@ public: cmTypeMacro(cmTargetLinkLibrariesCommand, cmCommand); private: + void LinkLibraryTypeSpecifierWarning(int left, int right); + static const char* LinkLibraryTypeNames[3]; };