diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 9a776fbde..c1d0e9d6d 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -64,6 +64,12 @@ bool cmAddLibraryCommand type = cmTarget::MODULE_LIBRARY; haveSpecifiedType = true; } + else if(libType == "OBJECT") + { + ++s; + type = cmTarget::OBJECT_LIBRARY; + haveSpecifiedType = true; + } else if(libType == "UNKNOWN") { ++s; @@ -118,6 +124,14 @@ bool cmAddLibraryCommand 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; + } // Make sure the target does not already exist. if(this->Makefile->FindTargetToUse(libName.c_str())) diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index ddff2d921..055aab032 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -633,6 +633,19 @@ cmTarget* cmComputeLinkDepends::FindTargetToLink(int depender_index, tgt = 0; } + if(tgt && tgt->GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "Target \"" << this->Target->GetName() << "\" links to " + "OBJECT library \"" << tgt->GetName() << "\" but this is not " + "allowed. " + "One may link only to STATIC or SHARED libraries, or to executables " + "with the ENABLE_EXPORTS property set."; + this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + tgt = 0; + } + // Return the target found, if any. return tgt; } diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index cb614d4f3..1cc17545a 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -124,6 +124,14 @@ bool cmExportCommand { targets.push_back(target); } + else if(target->GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "given OBJECT library \"" << *currentTarget + << "\" which may not be exported."; + this->SetError(e.str().c_str()); + return false; + } else { cmOStringStream e; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index afb1f3936..369eb5cf2 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -29,6 +29,8 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) //---------------------------------------------------------------------------- void cmGeneratorTarget::ClassifySources() { + bool isObjLib = this->Target->GetType() == cmTarget::OBJECT_LIBRARY; + std::vector badObjLib; std::vector const& sources = this->Target->GetSourceFiles(); for(std::vector::const_iterator si = sources.begin(); si != sources.end(); ++si) @@ -43,6 +45,7 @@ void cmGeneratorTarget::ClassifySources() else if(tsFlags.Type != cmTarget::SourceFileTypeNormal) { this->OSXContent.push_back(sf); + if(isObjLib) { badObjLib.push_back(sf); } } else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY")) { @@ -51,10 +54,12 @@ void cmGeneratorTarget::ClassifySources() else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { this->ExternalObjects.push_back(sf); + if(isObjLib) { badObjLib.push_back(sf); } } else if(cmSystemTools::LowerCase(sf->GetExtension()) == "def") { this->ModuleDefinitionFile = sf->GetFullPath(); + if(isObjLib) { badObjLib.push_back(sf); } } else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) { @@ -69,6 +74,22 @@ void cmGeneratorTarget::ClassifySources() else { this->ExtraSources.push_back(sf); + if(isObjLib) { badObjLib.push_back(sf); } } } + + if(!badObjLib.empty()) + { + cmOStringStream e; + e << "OBJECT library \"" << this->Target->GetName() << "\" contains:\n"; + for(std::vector::iterator i = badObjLib.begin(); + i != badObjLib.end(); ++i) + { + e << " " << (*i)->GetLocation().GetName() << "\n"; + } + e << "but may contain only headers and sources that compile."; + this->GlobalGenerator->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + } } diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 4b9e48791..7da4f8687 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -374,6 +374,12 @@ bool cmGlobalVisualStudioGenerator::ComputeTargetDepends() return true; } +//---------------------------------------------------------------------------- +static bool VSLinkable(cmTarget* t) +{ + return t->IsLinkable() || t->GetType() == cmTarget::OBJECT_LIBRARY; +} + //---------------------------------------------------------------------------- void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) { @@ -458,7 +464,7 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) di != utilDepends.end(); ++di) { cmTarget* dep = *di; - if(allowLinkable || !dep->IsLinkable() || linked.count(dep)) + if(allowLinkable || !VSLinkable(dep) || linked.count(dep)) { // Direct dependency allowed. vsTargetDepend.insert(dep->GetName()); diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index dca528d26..c65648737 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -357,7 +357,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) if(target->GetType() != cmTarget::EXECUTABLE && target->GetType() != cmTarget::STATIC_LIBRARY && target->GetType() != cmTarget::SHARED_LIBRARY && - target->GetType() != cmTarget::MODULE_LIBRARY) + target->GetType() != cmTarget::MODULE_LIBRARY && + target->GetType() != cmTarget::OBJECT_LIBRARY) { cmOStringStream e; e << "TARGETS given target \"" << (*targetIt) @@ -365,6 +366,14 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) this->SetError(e.str().c_str()); return false; } + else if(target->GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "TARGETS given OBJECT library \"" << (*targetIt) + << "\" which may not be installed."; + this->SetError(e.str().c_str()); + return false; + } // Store the target in the list to be installed. targets.push_back(target); } diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index c74dda063..5f9b6585e 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -90,6 +90,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, case cmTarget::STATIC_LIBRARY: type = cmInstallType_STATIC_LIBRARY; break; case cmTarget::SHARED_LIBRARY: type = cmInstallType_SHARED_LIBRARY; break; case cmTarget::MODULE_LIBRARY: type = cmInstallType_MODULE_LIBRARY; break; + case cmTarget::OBJECT_LIBRARY: case cmTarget::UTILITY: case cmTarget::GLOBAL_TARGET: case cmTarget::UNKNOWN_LIBRARY: diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 19537b5f7..ebfb58616 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1904,6 +1904,10 @@ bool cmLocalGenerator::GetRealDependency(const char* inName, case cmTarget::UNKNOWN_LIBRARY: dep = target->GetLocation(config); return true; + case cmTarget::OBJECT_LIBRARY: + // An object library has no single file on which to depend. + // This was listed to get the target-level dependency. + return false; case cmTarget::UTILITY: case cmTarget::GLOBAL_TARGET: // A utility target has no file on which to depend. This was listed diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 68a827251..aba2e38ea 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -853,6 +853,14 @@ cmMakefile::AddCustomCommandToTarget(const char* target, cmTargets::iterator ti = this->Targets.find(target); if(ti != this->Targets.end()) { + if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "Target \"" << target << "\" is an OBJECT library " + "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } // Add the command to the appropriate build step for the target. std::vector no_output; cmCustomCommand cc(this, no_output, depends, @@ -1912,8 +1920,11 @@ cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type, // wrong type ? default to STATIC if ( (type != cmTarget::STATIC_LIBRARY) && (type != cmTarget::SHARED_LIBRARY) - && (type != cmTarget::MODULE_LIBRARY)) + && (type != cmTarget::MODULE_LIBRARY) + && (type != cmTarget::OBJECT_LIBRARY)) { + this->IssueMessage(cmake::INTERNAL_ERROR, + "cmMakefile::AddLibrary given invalid target type."); type = cmTarget::STATIC_LIBRARY; } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e6be83ade..9e8668109 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -37,6 +37,8 @@ const char* cmTarget::GetTargetTypeName(TargetType targetType) return "MODULE_LIBRARY"; case cmTarget::SHARED_LIBRARY: return "SHARED_LIBRARY"; + case cmTarget::OBJECT_LIBRARY: + return "OBJECT_LIBRARY"; case cmTarget::EXECUTABLE: return "EXECUTABLE"; case cmTarget::UTILITY: diff --git a/Source/cmTarget.h b/Source/cmTarget.h index ff05cd3e9..e2502f06c 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -59,7 +59,8 @@ class cmTarget public: cmTarget(); enum TargetType { EXECUTABLE, STATIC_LIBRARY, - SHARED_LIBRARY, MODULE_LIBRARY, UTILITY, GLOBAL_TARGET, + SHARED_LIBRARY, MODULE_LIBRARY, + OBJECT_LIBRARY, UTILITY, GLOBAL_TARGET, UNKNOWN_LIBRARY}; static const char* GetTargetTypeName(TargetType targetType); enum CustomCommandType { PRE_BUILD, PRE_LINK, POST_BUILD }; diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 36c4ca8bd..dbea1c3bb 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -84,6 +84,16 @@ bool cmTargetLinkLibrariesCommand 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) {