diff options
Diffstat (limited to 'Source/cmAddLibraryCommand.cxx')
-rw-r--r-- | Source/cmAddLibraryCommand.cxx | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx new file mode 100644 index 0000000..cdc9f2a --- /dev/null +++ b/Source/cmAddLibraryCommand.cxx @@ -0,0 +1,450 @@ +/*============================================================================ + 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 "cmAddLibraryCommand.h" + +#include "cmake.h" + +// cmLibraryCommand +bool cmAddLibraryCommand +::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) +{ + if(args.size() < 1 ) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + // Library type defaults to value of BUILD_SHARED_LIBS, if it exists, + // otherwise it defaults to static library. + cmTarget::TargetType type = cmTarget::SHARED_LIBRARY; + if (cmSystemTools::IsOff(this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) + { + type = cmTarget::STATIC_LIBRARY; + } + bool excludeFromAll = false; + bool importTarget = false; + bool importGlobal = false; + + std::vector<std::string>::const_iterator s = args.begin(); + + std::string libName = *s; + + ++s; + + // If the second argument is "SHARED" or "STATIC", then it controls + // the type of library. Otherwise, it is treated as a source or + // source list name. There may be two keyword arguments, check for them + bool haveSpecifiedType = false; + bool isAlias = false; + while ( s != args.end() ) + { + std::string libType = *s; + if(libType == "STATIC") + { + if (type == cmTarget::INTERFACE_LIBRARY) + { + cmOStringStream e; + e << "INTERFACE library specified with conflicting STATIC type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmTarget::STATIC_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "SHARED") + { + if (type == cmTarget::INTERFACE_LIBRARY) + { + cmOStringStream e; + e << "INTERFACE library specified with conflicting SHARED type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmTarget::SHARED_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "MODULE") + { + if (type == cmTarget::INTERFACE_LIBRARY) + { + cmOStringStream e; + e << "INTERFACE library specified with conflicting MODULE type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmTarget::MODULE_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "OBJECT") + { + if (type == cmTarget::INTERFACE_LIBRARY) + { + cmOStringStream e; + e << "INTERFACE library specified with conflicting OBJECT type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmTarget::OBJECT_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "UNKNOWN") + { + if (type == cmTarget::INTERFACE_LIBRARY) + { + cmOStringStream e; + e << "INTERFACE library specified with conflicting UNKNOWN type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmTarget::UNKNOWN_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "ALIAS") + { + if (type == cmTarget::INTERFACE_LIBRARY) + { + cmOStringStream e; + e << "INTERFACE library specified with conflicting ALIAS type."; + this->SetError(e.str()); + return false; + } + ++s; + isAlias = true; + } + else if(libType == "INTERFACE") + { + if (haveSpecifiedType) + { + cmOStringStream e; + e << "INTERFACE library specified with conflicting/multiple types."; + this->SetError(e.str()); + return false; + } + if (isAlias) + { + cmOStringStream e; + e << "INTERFACE library specified with conflicting ALIAS type."; + this->SetError(e.str()); + return false; + } + if (excludeFromAll) + { + cmOStringStream e; + e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmTarget::INTERFACE_LIBRARY; + haveSpecifiedType = true; + } + else if(*s == "EXCLUDE_FROM_ALL") + { + if (type == cmTarget::INTERFACE_LIBRARY) + { + cmOStringStream e; + e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL."; + this->SetError(e.str()); + return false; + } + ++s; + excludeFromAll = true; + } + else if(*s == "IMPORTED") + { + ++s; + importTarget = true; + } + else if(importTarget && *s == "GLOBAL") + { + ++s; + importGlobal = true; + } + else if(type == cmTarget::INTERFACE_LIBRARY && *s == "GLOBAL") + { + cmOStringStream e; + e << "GLOBAL option may only be used with IMPORTED libraries."; + this->SetError(e.str()); + return false; + } + else + { + break; + } + } + + if (type == cmTarget::INTERFACE_LIBRARY) + { + if (s != args.end()) + { + cmOStringStream e; + e << "INTERFACE library requires no source arguments."; + this->SetError(e.str()); + return false; + } + if (importGlobal && !importTarget) + { + cmOStringStream e; + e << "INTERFACE library specified as GLOBAL, but not as IMPORTED."; + this->SetError(e.str()); + return false; + } + } + + bool nameOk = cmGeneratorExpression::IsValidTargetName(libName) && + !cmGlobalGenerator::IsReservedTarget(libName); + + if (nameOk && !importTarget && !isAlias) + { + nameOk = libName.find(":") == std::string::npos; + } + if (!nameOk) + { + cmake::MessageType messageType = cmake::AUTHOR_WARNING; + cmOStringStream e; + bool issueMessage = false; + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) + { + case cmPolicies::WARN: + if(type != cmTarget::INTERFACE_LIBRARY) + { + e << (this->Makefile->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0037)) << "\n"; + issueMessage = true; + } + case cmPolicies::OLD: + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + issueMessage = true; + messageType = cmake::FATAL_ERROR; + } + if (issueMessage) + { + e << "The target name \"" << libName << + "\" is reserved or not valid for certain " + "CMake features, such as generator expressions, and may result " + "in undefined behavior."; + this->Makefile->IssueMessage(messageType, e.str()); + + if (messageType == cmake::FATAL_ERROR) + { + return false; + } + } + } + + if (isAlias) + { + if(!cmGeneratorExpression::IsValidTargetName(libName)) + { + this->SetError("Invalid name for ALIAS: " + libName); + return false; + } + if(excludeFromAll) + { + this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense."); + return false; + } + if(importTarget || importGlobal) + { + this->SetError("IMPORTED with ALIAS is not allowed."); + return false; + } + if(args.size() != 3) + { + cmOStringStream e; + e << "ALIAS requires exactly one target argument."; + this->SetError(e.str()); + return false; + } + + const char *aliasedName = s->c_str(); + if(this->Makefile->IsAlias(aliasedName)) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" is itself an ALIAS."; + this->SetError(e.str()); + return false; + } + cmTarget *aliasedTarget = + this->Makefile->FindTargetToUse(aliasedName, true); + if(!aliasedTarget) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" does not already " + "exist."; + this->SetError(e.str()); + return false; + } + cmTarget::TargetType aliasedType = aliasedTarget->GetType(); + if(aliasedType != cmTarget::SHARED_LIBRARY + && aliasedType != cmTarget::STATIC_LIBRARY + && aliasedType != cmTarget::MODULE_LIBRARY + && aliasedType != cmTarget::OBJECT_LIBRARY + && aliasedType != cmTarget::INTERFACE_LIBRARY) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" is not a library."; + this->SetError(e.str()); + return false; + } + if(aliasedTarget->IsImported()) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" is IMPORTED."; + this->SetError(e.str()); + return false; + } + this->Makefile->AddAlias(libName, aliasedTarget); + return true; + } + + if(importTarget && excludeFromAll) + { + this->SetError("excludeFromAll with IMPORTED target makes no sense."); + return false; + } + + /* ideally we should check whether for the linker language of the target + CMAKE_${LANG}_CREATE_SHARED_LIBRARY is defined and if not default to + STATIC. But at this point we know only the name of the target, but not + yet its linker language. */ + if ((type != cmTarget::STATIC_LIBRARY) && + (type != cmTarget::OBJECT_LIBRARY) && + (type != cmTarget::INTERFACE_LIBRARY) && + (this->Makefile->GetCMakeInstance()->GetPropertyAsBool( + "TARGET_SUPPORTS_SHARED_LIBS") == false)) + { + cmOStringStream w; + w << + "ADD_LIBRARY called with " << + (type==cmTarget::SHARED_LIBRARY ? "SHARED" : "MODULE") << + " option but the target platform does not support dynamic linking. " + "Building a STATIC library instead. This may lead to problems."; + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + type = cmTarget::STATIC_LIBRARY; + } + + // Handle imported target creation. + if(importTarget) + { + // The IMPORTED signature requires a type to be specified explicitly. + if (!haveSpecifiedType) + { + this->SetError("called with IMPORTED argument but no library type."); + return false; + } + if(type == cmTarget::OBJECT_LIBRARY) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "The OBJECT library type may not be used for IMPORTED libraries." + ); + return true; + } + if(type == cmTarget::INTERFACE_LIBRARY) + { + if (!cmGeneratorExpression::IsValidTargetName(libName)) + { + cmOStringStream e; + e << "Invalid name for IMPORTED INTERFACE library target: " << libName; + this->SetError(e.str()); + return false; + } + } + + // Make sure the target does not already exist. + if(this->Makefile->FindTargetToUse(libName)) + { + cmOStringStream e; + e << "cannot create imported target \"" << libName + << "\" because another target with the same name already exists."; + this->SetError(e.str()); + return false; + } + + // Create the imported target. + this->Makefile->AddImportedTarget(libName, type, importGlobal); + return true; + } + + // A non-imported target may not have UNKNOWN type. + if(type == cmTarget::UNKNOWN_LIBRARY) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "The UNKNOWN library type may be used only for IMPORTED libraries." + ); + return true; + } + + // Enforce name uniqueness. + { + std::string msg; + if(!this->Makefile->EnforceUniqueName(libName, msg)) + { + this->SetError(msg); + return false; + } + } + + std::vector<std::string> srclists; + + if(type == cmTarget::INTERFACE_LIBRARY) + { + if (!cmGeneratorExpression::IsValidTargetName(libName) + || libName.find("::") != std::string::npos) + { + cmOStringStream e; + e << "Invalid name for INTERFACE library target: " << libName; + this->SetError(e.str()); + return false; + } + + this->Makefile->AddLibrary(libName, + type, + srclists, + excludeFromAll); + return true; + } + + if (s == args.end()) + { + std::string msg = "You have called ADD_LIBRARY for library "; + msg += args[0]; + msg += " without any source files. This typically indicates a problem "; + msg += "with your CMakeLists.txt file"; + cmSystemTools::Message(msg.c_str() ,"Warning"); + } + + while (s != args.end()) + { + srclists.push_back(*s); + ++s; + } + + this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll); + + return true; +} + + |