diff options
author | Brad King <brad.king@kitware.com> | 2012-03-12 18:40:58 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2012-03-16 14:12:15 (GMT) |
commit | c403f27a2de2327f5c895972e16a81d80968c40c (patch) | |
tree | 20836fe0e36e6ba3abaef61bf7ba394bfcbb02b8 /Source | |
parent | 3a53005f7dd5e582b855ef1f3c0e6814ce7d024a (diff) | |
download | CMake-c403f27a2de2327f5c895972e16a81d80968c40c.zip CMake-c403f27a2de2327f5c895972e16a81d80968c40c.tar.gz CMake-c403f27a2de2327f5c895972e16a81d80968c40c.tar.bz2 |
Add $<TARGET_OBJECTS:...> expression to use an object library
For now do not allow an OBJECT library to reference other object
libraries. Teach cmTarget::ComputeLinkImplementation to include the
languages of object libraries used by a target.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 74 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 5 | ||||
-rw-r--r-- | Source/cmLocalVisualStudio6Generator.cxx | 36 | ||||
-rw-r--r-- | Source/cmLocalVisualStudio6Generator.h | 2 | ||||
-rw-r--r-- | Source/cmLocalVisualStudio7Generator.cxx | 72 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 3 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 42 | ||||
-rw-r--r-- | Source/cmTarget.h | 7 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 44 |
9 files changed, 278 insertions, 7 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 369eb5c..c9911a5 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -24,6 +24,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); this->ClassifySources(); + this->LookupObjectLibraries(); } //---------------------------------------------------------------------------- @@ -93,3 +94,76 @@ void cmGeneratorTarget::ClassifySources() this->Target->GetBacktrace()); } } + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::LookupObjectLibraries() +{ + std::vector<std::string> const& objLibs = + this->Target->GetObjectLibraries(); + for(std::vector<std::string>::const_iterator oli = objLibs.begin(); + oli != objLibs.end(); ++oli) + { + std::string const& objLibName = *oli; + if(cmTarget* objLib = this->Makefile->FindTargetToUse(objLibName.c_str())) + { + if(objLib->GetType() == cmTarget::OBJECT_LIBRARY) + { + if(this->Target->GetType() != cmTarget::EXECUTABLE && + this->Target->GetType() != cmTarget::STATIC_LIBRARY && + this->Target->GetType() != cmTarget::SHARED_LIBRARY && + this->Target->GetType() != cmTarget::MODULE_LIBRARY) + { + this->GlobalGenerator->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, + "Only executables and non-OBJECT libraries may " + "reference target objects.", + this->Target->GetBacktrace()); + return; + } + this->Target->AddUtility(objLib->GetName()); + this->ObjectLibraries.push_back(objLib); + } + else + { + cmOStringStream e; + e << "Objects of target \"" << objLibName + << "\" referenced but is not an OBJECT library."; + this->GlobalGenerator->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + return; + } + } + else + { + cmOStringStream e; + e << "Objects of target \"" << objLibName + << "\" referenced but no such target exists."; + this->GlobalGenerator->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + return; + } + } +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs) +{ + for(std::vector<cmTarget*>::const_iterator + ti = this->ObjectLibraries.begin(); + ti != this->ObjectLibraries.end(); ++ti) + { + cmTarget* objLib = *ti; + cmGeneratorTarget* ogt = + this->GlobalGenerator->GetGeneratorTarget(objLib); + for(std::vector<cmSourceFile*>::const_iterator + si = ogt->ObjectSources.begin(); + si != ogt->ObjectSources.end(); ++si) + { + std::string obj = ogt->ObjectDirectory; + obj += ogt->Objects[*si]; + objs.push_back(obj); + } + } +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index b083ba1..6319d82 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -48,8 +48,13 @@ public: time config name placeholder if needed for the generator. */ std::string ObjectDirectory; + std::vector<cmTarget*> ObjectLibraries; + + void UseObjectLibraries(std::vector<std::string>& objs); + private: void ClassifySources(); + void LookupObjectLibraries(); cmGeneratorTarget(cmGeneratorTarget const&); void operator=(cmGeneratorTarget const&); diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index f53ad0e..5b99dfd 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -1428,6 +1428,16 @@ void cmLocalVisualStudio6Generator staticLibOptionsRelWithDebInfo += " "; staticLibOptionsRelWithDebInfo = libflagsRelWithDebInfo; } + std::string objects; + this->OutputObjects(target, "LIB", objects); + if(!objects.empty()) + { + objects = "\n" + objects; + staticLibOptionsDebug += objects; + staticLibOptionsRelease += objects; + staticLibOptionsMinSizeRel += objects; + staticLibOptionsRelWithDebInfo += objects; + } } // Add the export symbol definition for shared library objects. @@ -1587,7 +1597,7 @@ void cmLocalVisualStudio6Generator std::string flagsDebug = " "; std::string flagsDebugRel = " "; if(target.GetType() >= cmTarget::EXECUTABLE && - target.GetType() <= cmTarget::MODULE_LIBRARY) + target.GetType() <= cmTarget::OBJECT_LIBRARY) { const char* linkLanguage = target.GetLinkerLanguage(); if(!linkLanguage) @@ -1742,6 +1752,8 @@ void cmLocalVisualStudio6Generator ItemVector const& linkLibs = cli.GetItems(); std::vector<std::string> const& linkDirs = cli.GetDirectories(); + this->OutputObjects(target, "LINK", options); + // Build the link options code. for(std::vector<std::string>::const_iterator d = linkDirs.begin(); d != linkDirs.end(); ++d) @@ -1786,6 +1798,28 @@ void cmLocalVisualStudio6Generator } } +//---------------------------------------------------------------------------- +void cmLocalVisualStudio6Generator +::OutputObjects(cmTarget& target, const char* tool, + std::string& options) +{ + // VS 6 does not support per-config source locations so we + // list object library content on the link line instead. + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + std::vector<std::string> objs; + gt->UseObjectLibraries(objs); + for(std::vector<std::string>::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + options += "# ADD "; + options += tool; + options += "32 "; + options += this->ConvertToOptionallyRelativeOutputPath(oi->c_str()); + options += "\n"; + } +} + std::string cmLocalVisualStudio6Generator ::GetTargetDirectory(cmTarget const&) const diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h index d36d633..a680633 100644 --- a/Source/cmLocalVisualStudio6Generator.h +++ b/Source/cmLocalVisualStudio6Generator.h @@ -87,6 +87,8 @@ private: void ComputeLinkOptions(cmTarget& target, const char* configName, const std::string extraOptions, std::string& options); + void OutputObjects(cmTarget& target, const char* tool, + std::string& options); std::string GetTargetIncludeOptions(cmTarget &target); std::vector<std::string> Configurations; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 2f145a6..363d370 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -39,6 +39,7 @@ public: LocalGenerator(e) {} typedef cmComputeLinkInformation::ItemVector ItemVector; void OutputLibraries(std::ostream& fout, ItemVector const& libs); + void OutputObjects(std::ostream& fout, cmTarget* t, const char* isep = 0); private: cmLocalVisualStudio7Generator* LocalGenerator; }; @@ -1033,6 +1034,15 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, fout << "\t\t\t<Tool\n" << "\t\t\t\tName=\"" << tool << "\"\n"; + if(this->GetVersion() < VS8) + { + cmOStringStream libdeps; + this->Internal->OutputObjects(libdeps, &target); + if(!libdeps.str().empty()) + { + fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str() << "\"\n"; + } + } std::string libflags; if(const char* flags = target.GetProperty("STATIC_LIBRARY_FLAGS")) { @@ -1093,8 +1103,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " - << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()) - << " "; + << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + if(this->GetVersion() < VS8) + { + this->Internal->OutputObjects(fout, &target, " "); + } + fout << " "; this->Internal->OutputLibraries(fout, cli.GetItems()); fout << "\"\n"; temp = target.GetDirectory(configName); @@ -1174,8 +1188,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " - << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()) - << " "; + << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + if(this->GetVersion() < VS8) + { + this->Internal->OutputObjects(fout, &target, " "); + } + fout << " "; this->Internal->OutputLibraries(fout, cli.GetItems()); fout << "\"\n"; temp = target.GetDirectory(configName); @@ -1263,6 +1281,30 @@ cmLocalVisualStudio7GeneratorInternals //---------------------------------------------------------------------------- void +cmLocalVisualStudio7GeneratorInternals +::OutputObjects(std::ostream& fout, cmTarget* t, const char* isep) +{ + // VS < 8 does not support per-config source locations so we + // list object library content on the link line instead. + cmLocalVisualStudio7Generator* lg = this->LocalGenerator; + cmGeneratorTarget* gt = + lg->GetGlobalGenerator()->GetGeneratorTarget(t); + std::vector<std::string> objs; + gt->UseObjectLibraries(objs); + const char* sep = isep? isep : ""; + for(std::vector<std::string>::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string rel = lg->Convert(oi->c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::UNCHANGED); + fout << sep << lg->ConvertToXMLOutputPath(rel.c_str()); + sep = " "; + } +} + +//---------------------------------------------------------------------------- +void cmLocalVisualStudio7Generator ::OutputLibraryDirectories(std::ostream& fout, std::vector<std::string> const& dirs) @@ -1344,7 +1386,27 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, this->WriteGroup(&sg, target, fout, libName, configs); } - //} + if(this->GetVersion() >= VS8) + { + // VS >= 8 support per-config source locations so we + // list object library content as external objects. + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + std::vector<std::string> objs; + gt->UseObjectLibraries(objs); + if(!objs.empty()) + { + // TODO: Separate sub-filter for each object library used? + fout << "\t\t<Filter Name=\"Object Libraries\">\n"; + for(std::vector<std::string>::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string o = this->ConvertToXMLOutputPathSingle(oi->c_str()); + fout << "\t\t\t<File RelativePath=\"" << o << "\" />\n"; + } + fout << "\t\t</Filter>\n"; + } + } fout << "\t</Files>\n"; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index d0cfd99..a0e0481 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -174,6 +174,9 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // Generate this object file's rule file. this->WriteObjectRuleFiles(**si); } + + // Add object library contents as external objects. + this->GeneratorTarget->UseObjectLibraries(this->ExternalObjects); } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 9e86681..708a989 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1724,7 +1724,15 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs) for(std::vector<std::string>::const_iterator i = srcs.begin(); i != srcs.end(); ++i) { - this->AddSource(i->c_str()); + const char* src = i->c_str(); + if(src[0] == '$' && src[1] == '<') + { + this->ProcessSourceExpression(*i); + } + else + { + this->AddSource(src); + } } } @@ -1743,6 +1751,24 @@ cmSourceFile* cmTarget::AddSource(const char* s) } //---------------------------------------------------------------------------- +void cmTarget::ProcessSourceExpression(std::string const& expr) +{ + if(strncmp(expr.c_str(), "$<TARGET_OBJECTS:", 17) == 0 && + expr[expr.size()-1] == '>') + { + std::string objLibName = expr.substr(17, expr.size()-18); + this->ObjectLibraries.push_back(objLibName); + } + else + { + cmOStringStream e; + e << "Unrecognized generator expression:\n" + << " " << expr; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + } +} + +//---------------------------------------------------------------------------- struct cmTarget::SourceFileFlags cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) { @@ -4542,7 +4568,21 @@ void cmTarget::ComputeLinkImplementation(const char* config, // This target needs runtime libraries for its source languages. std::set<cmStdString> languages; + // Get languages used in our source files. this->GetLanguages(languages); + // Get languages used in object library sources. + for(std::vector<std::string>::iterator i = this->ObjectLibraries.begin(); + i != this->ObjectLibraries.end(); ++i) + { + if(cmTarget* objLib = this->Makefile->FindTargetToUse(i->c_str())) + { + if(objLib->GetType() == cmTarget::OBJECT_LIBRARY) + { + objLib->GetLanguages(languages); + } + } + } + // Copy the set of langauges to the link implementation. for(std::set<cmStdString>::iterator li = languages.begin(); li != languages.end(); ++li) { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index e2502f0..d41c827 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -117,6 +117,10 @@ public: */ std::vector<cmSourceFile*> const& GetSourceFiles(); void AddSourceFile(cmSourceFile* sf); + std::vector<std::string> const& GetObjectLibraries() const + { + return this->ObjectLibraries; + } /** Get sources that must be built before the given source. */ std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile* sf); @@ -549,6 +553,7 @@ private: std::vector<cmCustomCommand> PostBuildCommands; TargetType TargetTypeValue; std::vector<cmSourceFile*> SourceFiles; + std::vector<std::string> ObjectLibraries; LinkLibraryVectorType LinkLibraries; LinkLibraryVectorType PrevLinkedLibraries; bool LinkLibrariesAnalyzed; @@ -590,6 +595,8 @@ private: void MaybeInvalidatePropertyCache(const char* prop); + void ProcessSourceExpression(std::string const& expr); + // The cmMakefile instance that owns this target. This should // always be set. cmMakefile* Makefile; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index db37dfc..054b86b 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -635,6 +635,25 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->WriteGroupSources("Midl", idls, sourceGroups); this->WriteGroupSources("CustomBuild", customBuild, sourceGroups); + // Add object library contents as external objects. + std::vector<std::string> objs; + this->GeneratorTarget->UseObjectLibraries(objs); + if(!objs.empty()) + { + this->WriteString("<ItemGroup>\n", 1); + for(std::vector<std::string>::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string obj = *oi; + this->WriteString("<Object Include=\"", 2); + this->ConvertToWindowsSlash(obj); + (*this->BuildFileStream ) << obj << "\">\n"; + this->WriteString("<Filter>Object Libraries</Filter>\n", 3); + this->WriteString("</Object>\n", 2); + } + this->WriteString("</ItemGroup>\n", 1); + } + this->WriteString("<ItemGroup>\n", 1); for(std::set<cmSourceGroup*>::iterator g = groupsUsed.begin(); g != groupsUsed.end(); ++g) @@ -658,6 +677,18 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->WriteString("</Filter>\n", 2); } } + if(!objs.empty()) + { + this->WriteString("<Filter Include=\"Object Libraries\">\n", 2); + std::string guidName = "SG_Filter_Object Libraries"; + this->GlobalGenerator->CreateGUID(guidName.c_str()); + this->WriteString("<UniqueIdentifier>", 3); + std::string guid = + this->GlobalGenerator->GetGUID(guidName.c_str()); + (*this->BuildFileStream) << "{" << guid << "}" + << "</UniqueIdentifier>\n"; + this->WriteString("</Filter>\n", 2); + } this->WriteString("</ItemGroup>\n", 1); this->WriteGroupSources("None", none, sourceGroups); this->WriteString("</Project>\n", 0); @@ -873,6 +904,19 @@ void cmVisualStudio10TargetGenerator::WriteCLSources() (*this->BuildFileStream ) << " />\n"; } } + + // Add object library contents as external objects. + std::vector<std::string> objs; + this->GeneratorTarget->UseObjectLibraries(objs); + for(std::vector<std::string>::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string obj = *oi; + this->WriteString("<Object Include=\"", 2); + this->ConvertToWindowsSlash(obj); + (*this->BuildFileStream ) << obj << "\" />\n"; + } + this->WriteString("</ItemGroup>\n", 1); } |