diff options
Diffstat (limited to 'Source/cmAddLibraryCommand.cxx')
-rw-r--r-- | Source/cmAddLibraryCommand.cxx | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx new file mode 100644 index 0000000..5296cbb --- /dev/null +++ b/Source/cmAddLibraryCommand.cxx @@ -0,0 +1,445 @@ +/*============================================================================ + 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" +#include "cmState.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. + cmState::TargetType type = cmState::SHARED_LIBRARY; + if (cmSystemTools::IsOff(this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) + { + type = cmState::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 == cmState::INTERFACE_LIBRARY) + { + std::ostringstream e; + e << "INTERFACE library specified with conflicting STATIC type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmState::STATIC_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "SHARED") + { + if (type == cmState::INTERFACE_LIBRARY) + { + std::ostringstream e; + e << "INTERFACE library specified with conflicting SHARED type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmState::SHARED_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "MODULE") + { + if (type == cmState::INTERFACE_LIBRARY) + { + std::ostringstream e; + e << "INTERFACE library specified with conflicting MODULE type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmState::MODULE_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "OBJECT") + { + if (type == cmState::INTERFACE_LIBRARY) + { + std::ostringstream e; + e << "INTERFACE library specified with conflicting OBJECT type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmState::OBJECT_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "UNKNOWN") + { + if (type == cmState::INTERFACE_LIBRARY) + { + std::ostringstream e; + e << "INTERFACE library specified with conflicting UNKNOWN type."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmState::UNKNOWN_LIBRARY; + haveSpecifiedType = true; + } + else if(libType == "ALIAS") + { + if (type == cmState::INTERFACE_LIBRARY) + { + std::ostringstream e; + e << "INTERFACE library specified with conflicting ALIAS type."; + this->SetError(e.str()); + return false; + } + ++s; + isAlias = true; + } + else if(libType == "INTERFACE") + { + if (haveSpecifiedType) + { + std::ostringstream e; + e << "INTERFACE library specified with conflicting/multiple types."; + this->SetError(e.str()); + return false; + } + if (isAlias) + { + std::ostringstream e; + e << "INTERFACE library specified with conflicting ALIAS type."; + this->SetError(e.str()); + return false; + } + if (excludeFromAll) + { + std::ostringstream e; + e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL."; + this->SetError(e.str()); + return false; + } + ++s; + type = cmState::INTERFACE_LIBRARY; + haveSpecifiedType = true; + } + else if(*s == "EXCLUDE_FROM_ALL") + { + if (type == cmState::INTERFACE_LIBRARY) + { + std::ostringstream 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 == cmState::INTERFACE_LIBRARY && *s == "GLOBAL") + { + std::ostringstream e; + e << "GLOBAL option may only be used with IMPORTED libraries."; + this->SetError(e.str()); + return false; + } + else + { + break; + } + } + + if (type == cmState::INTERFACE_LIBRARY) + { + if (s != args.end()) + { + std::ostringstream e; + e << "INTERFACE library requires no source arguments."; + this->SetError(e.str()); + return false; + } + if (importGlobal && !importTarget) + { + std::ostringstream 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; + std::ostringstream e; + bool issueMessage = false; + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) + { + case cmPolicies::WARN: + if(type != cmState::INTERFACE_LIBRARY) + { + e << cmPolicies::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) + { + std::ostringstream 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)) + { + std::ostringstream 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) + { + std::ostringstream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" does not already " + "exist."; + this->SetError(e.str()); + return false; + } + cmState::TargetType aliasedType = aliasedTarget->GetType(); + if(aliasedType != cmState::SHARED_LIBRARY + && aliasedType != cmState::STATIC_LIBRARY + && aliasedType != cmState::MODULE_LIBRARY + && aliasedType != cmState::OBJECT_LIBRARY + && aliasedType != cmState::INTERFACE_LIBRARY) + { + std::ostringstream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" is not a library."; + this->SetError(e.str()); + return false; + } + if(aliasedTarget->IsImported()) + { + std::ostringstream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" is IMPORTED."; + this->SetError(e.str()); + return false; + } + this->Makefile->AddAlias(libName, aliasedName); + 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 == cmState::SHARED_LIBRARY || + type == cmState::MODULE_LIBRARY) && + (this->Makefile->GetState()->GetGlobalPropertyAsBool( + "TARGET_SUPPORTS_SHARED_LIBS") == false)) + { + std::ostringstream w; + w << + "ADD_LIBRARY called with " << + (type==cmState::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 = cmState::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 == cmState::OBJECT_LIBRARY) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "The OBJECT library type may not be used for IMPORTED libraries." + ); + return true; + } + if(type == cmState::INTERFACE_LIBRARY) + { + if (!cmGeneratorExpression::IsValidTargetName(libName)) + { + std::ostringstream 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)) + { + std::ostringstream 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 == cmState::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 == cmState::INTERFACE_LIBRARY) + { + if (!cmGeneratorExpression::IsValidTargetName(libName) + || libName.find("::") != std::string::npos) + { + std::ostringstream 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"); + } + + srclists.insert(srclists.end(), s, args.end()); + + this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll); + + return true; +} + + |