123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- /*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
- ============================================================================*/
- #include "cmTargetLinkLibrariesCommand.h"
- #include "cmGeneratorExpression.h"
- const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] =
- {
- "general",
- "debug",
- "optimized"
- };
- // cmTargetLinkLibrariesCommand
- bool cmTargetLinkLibrariesCommand
- ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
- {
- // must have one argument
- if(args.size() < 1)
- {
- this->SetError("called with incorrect number of arguments");
- return false;
- }
- // Lookup the target for which libraries are specified.
- this->Target =
- this->Makefile->GetCMakeInstance()
- ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
- if(!this->Target)
- {
- cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
- cmOStringStream e;
- e << "Cannot specify link libraries for target \"" << args[0] << "\" "
- << "which is not built by this project.";
- // The bad target is the only argument. Check how policy CMP0016 is set,
- // and accept, warn or fail respectively:
- if (args.size() < 2)
- {
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016))
- {
- case cmPolicies::WARN:
- t = cmake::AUTHOR_WARNING;
- // Print the warning.
- e << "\n"
- << "CMake does not support this but it used to work accidentally "
- << "and is being allowed for compatibility."
- << "\n" << this->Makefile->GetPolicies()->
- GetPolicyWarning(cmPolicies::CMP0016);
- break;
- case cmPolicies::OLD: // OLD behavior does not warn.
- t = cmake::MESSAGE;
- break;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- e << "\n" << this->Makefile->GetPolicies()->
- GetRequiredPolicyError(cmPolicies::CMP0016);
- break;
- case cmPolicies::NEW: // NEW behavior prints the error.
- default:
- break;
- }
- }
- // now actually print the message
- switch(t)
- {
- case cmake::AUTHOR_WARNING:
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
- break;
- case cmake::FATAL_ERROR:
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- cmSystemTools::SetFatalErrorOccured();
- break;
- default:
- break;
- }
- return true;
- }
- if(this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
- {
- cmOStringStream e;
- e << "Object library target \"" << args[0] << "\" "
- << "may not link to anything.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
- // but we might not have any libs after variable expansion
- if(args.size() < 2)
- {
- return true;
- }
- // Keep track of link configuration specifiers.
- cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
- bool haveLLT = false;
- // Start with primary linking and switch to link interface
- // specification if the keyword is encountered as the first argument.
- this->CurrentProcessingState = ProcessingLinkLibraries;
- // add libraries, note that there is an optional prefix
- // of debug and optimized that can be used
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "LINK_INTERFACE_LIBRARIES")
- {
- this->CurrentProcessingState = ProcessingLinkInterface;
- if(i != 1)
- {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "The LINK_INTERFACE_LIBRARIES option must appear as the second "
- "argument, just after the target name."
- );
- return true;
- }
- }
- else if(args[i] == "LINK_PUBLIC")
- {
- if(i != 1 && this->CurrentProcessingState != ProcessingPrivateInterface)
- {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
- "argument, just after the target name."
- );
- return true;
- }
- this->CurrentProcessingState = ProcessingPublicInterface;
- }
- else if(args[i] == "LINK_PRIVATE")
- {
- if(i != 1 && this->CurrentProcessingState != ProcessingPublicInterface)
- {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
- "argument, just after the target name."
- );
- return true;
- }
- this->CurrentProcessingState = ProcessingPrivateInterface;
- }
- else if(args[i] == "debug")
- {
- if(haveLLT)
- {
- this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::DEBUG);
- }
- llt = cmTarget::DEBUG;
- haveLLT = true;
- }
- else if(args[i] == "optimized")
- {
- if(haveLLT)
- {
- this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::OPTIMIZED);
- }
- llt = cmTarget::OPTIMIZED;
- haveLLT = true;
- }
- else if(args[i] == "general")
- {
- if(haveLLT)
- {
- this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::GENERAL);
- }
- llt = cmTarget::GENERAL;
- haveLLT = true;
- }
- else if(haveLLT)
- {
- // The link type was specified by the previous argument.
- haveLLT = false;
- this->HandleLibrary(args[i].c_str(), llt);
- }
- else
- {
- // 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)
- llt = cmTarget::GENERAL;
- std::string linkType = args[0];
- linkType += "_LINK_TYPE";
- const char* linkTypeString =
- this->Makefile->GetDefinition( linkType.c_str() );
- if(linkTypeString)
- {
- if(strcmp(linkTypeString, "debug") == 0)
- {
- llt = cmTarget::DEBUG;
- }
- if(strcmp(linkTypeString, "optimized") == 0)
- {
- llt = cmTarget::OPTIMIZED;
- }
- }
- this->HandleLibrary(args[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();
- }
- // If any of the LINK_ options were given, make sure the
- // LINK_INTERFACE_LIBRARIES target property exists.
- // Use of any of the new keywords implies awareness of
- // this property. And if no libraries are named, it should
- // result in an empty link interface.
- if(this->CurrentProcessingState != ProcessingLinkLibraries &&
- !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES"))
- {
- this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
- }
- 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());
- }
- //----------------------------------------------------------------------------
- static std::string compileProperty(cmTarget *tgt, const std::string &lib,
- bool isGenex,
- const std::string &property,
- cmTarget::LinkLibraryType llt)
- {
- std::string value = !isGenex ? "$<LINKED:" + lib + ">"
- : "$<$<TARGET_DEFINED:" + lib + ">:" +
- "$<TARGET_PROPERTY:" + lib +
- ",INTERFACE_" + property + ">"
- ">";
- return tgt->GetDebugGeneratorExpressions(value, llt);
- }
- //----------------------------------------------------------------------------
- void
- cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
- cmTarget::LinkLibraryType llt)
- {
- const bool isGenex = cmGeneratorExpression::Find(lib) != std::string::npos;
- const bool potentialTargetName
- = cmGeneratorExpression::IsValidTargetName(lib);
- if (potentialTargetName || isGenex)
- {
- this->Target->AppendProperty("INCLUDE_DIRECTORIES",
- compileProperty(this->Target, lib,
- isGenex,
- "INCLUDE_DIRECTORIES", llt).c_str());
- this->Target->AppendProperty("COMPILE_DEFINITIONS",
- compileProperty(this->Target, lib,
- isGenex,
- "COMPILE_DEFINITIONS", llt).c_str());
- }
- // Handle normal case first.
- if(this->CurrentProcessingState != ProcessingLinkInterface)
- {
- this->Makefile
- ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
- if (this->CurrentProcessingState != ProcessingPublicInterface)
- {
- // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
- return;
- }
- }
- if (potentialTargetName || isGenex)
- {
- this->Target->AppendProperty("INTERFACE_COMPILE_DEFINITIONS",
- compileProperty(this->Target, lib,
- isGenex,
- "COMPILE_DEFINITIONS", llt).c_str());
- this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
- compileProperty(this->Target, lib,
- isGenex,
- "INCLUDE_DIRECTORIES", llt).c_str());
- }
- // Get the list of configurations considered to be DEBUG.
- std::vector<std::string> const& debugConfigs =
- this->Makefile->GetCMakeInstance()->GetDebugConfigs();
- std::string prop;
- // Include this library in the link interface for the target.
- if(llt == cmTarget::DEBUG || llt == cmTarget::GENERAL)
- {
- // Put in the DEBUG configuration interfaces.
- for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
- i != debugConfigs.end(); ++i)
- {
- prop = "LINK_INTERFACE_LIBRARIES_";
- prop += *i;
- this->Target->AppendProperty(prop.c_str(), lib);
- }
- }
- if(llt == cmTarget::OPTIMIZED || llt == cmTarget::GENERAL)
- {
- // Put in the non-DEBUG configuration interfaces.
- this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);
- // Make sure the DEBUG configuration interfaces exist so that the
- // general one will not be used as a fall-back.
- for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
- i != debugConfigs.end(); ++i)
- {
- prop = "LINK_INTERFACE_LIBRARIES_";
- prop += *i;
- if(!this->Target->GetProperty(prop.c_str()))
- {
- this->Target->SetProperty(prop.c_str(), "");
- }
- }
- }
- }
|