summaryrefslogtreecommitdiffstats
path: root/Source/cmAddLibraryCommand.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmAddLibraryCommand.cxx')
-rw-r--r--Source/cmAddLibraryCommand.cxx450
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;
+}
+
+