From a1c4905f723f9d99bd481580f9fe24fdaf81b174 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 12 Feb 2013 11:29:09 +0100 Subject: [PATCH] Use the link information as a source of compile definitions and includes. After evaluating the INTERFACE_INCLUDE_DIRECTORIES, of a target in a generator expression, also read the INTERFACE_INCLUDE_DIRECTORIES of its link interface dependencies. That means that code such as this will result in the 'user' target using /bar/include and /foo/include: add_library(foo ...) target_include_directories(foo INTERFACE /foo/include) add_library(bar ...) target_include_directories(bar INTERFACE /bar/include) target_link_libraries(bar LINK_PUBLIC foo) add_executable(user ...) target_include_directories(user PRIVATE $) Also process the interface include directories from direct link dependencies for in-build targets. The situation is similar for the INTERFACE_COMPILE_DEFINITIONS. The include directories related code is currently more complex because we also need to store a backtrace at configure-time for the purpose of debugging includes. The compile definitions related code will use the same pattern in the future. This is not a change in behavior, as existing code has the same effect, but that existing code will be removed in follow-up commits. --- Source/cmGeneratorExpressionEvaluator.cxx | 69 ++++++- Source/cmTarget.cxx | 223 +++++++++++++++------- Source/cmTarget.h | 1 + Source/cmTargetLinkLibrariesCommand.cxx | 8 + 4 files changed, 231 insertions(+), 70 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 98e0ada67b..6c1c12a329 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -451,15 +451,68 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } const char *prop = target->GetProperty(propertyName.c_str()); + + std::string linkedTargetsContent; + + if (dagCheckerParent) + { + if (dagCheckerParent->EvaluatingLinkLibraries()) + { + if(!prop) + { + return std::string(); + } + } + else + { + assert(dagCheckerParent->EvaluatingIncludeDirectories() + || dagCheckerParent->EvaluatingCompileDefinitions()); + + if (propertyName == "INTERFACE_INCLUDE_DIRECTORIES" + || propertyName == "INTERFACE_COMPILE_DEFINITIONS") + { + const cmTarget::LinkInterface *iface = target->GetLinkInterface( + context->Config, + context->HeadTarget); + if(iface) + { + cmGeneratorExpression ge(context->Backtrace); + + std::string sep; + std::string depString; + for (std::vector::const_iterator + it = iface->Libraries.begin(); + it != iface->Libraries.end(); ++it) + { + if (context->Makefile->FindTargetToUse(it->c_str())) + { + depString += + sep + "$"; + sep = ";"; + } + } + cmsys::auto_ptr cge = + ge.Parse(depString); + linkedTargetsContent = cge->Evaluate(context->Makefile, + context->Config, + context->Quiet, + context->HeadTarget, + target, + &dagChecker); + if (cge->GetHadContextSensitiveCondition()) + { + context->HadContextSensitiveCondition = true; + } + } + } + } + } + if (!prop) { if (target->IsImported()) { - return std::string(); - } - if (dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries()) - { - return std::string(); + return linkedTargetsContent; } if (target->IsLinkInterfaceDependentBoolProperty(propertyName, context->Config)) @@ -480,7 +533,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return propContent ? propContent : ""; } - return std::string(); + return linkedTargetsContent; } for (size_t i = 0; @@ -503,6 +556,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { context->HadContextSensitiveCondition = true; } + if (!linkedTargetsContent.empty()) + { + result += (result.empty() ? "" : ";") + linkedTargetsContent; + } return result; } } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 6da6957c21..003f3d8303 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -137,6 +137,7 @@ public: std::vector CachedIncludes; }; std::vector IncludeDirectoriesEntries; + std::vector LinkInterfaceIncludeDirectoriesEntries; }; //---------------------------------------------------------------------------- @@ -2742,6 +2743,12 @@ void cmTarget::AppendBuildInterfaceIncludes() } } +//---------------------------------------------------------------------------- +void cmTarget::AppendTllInclude(const cmValueWithOrigin &entry) +{ + this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry); +} + //---------------------------------------------------------------------------- void cmTarget::InsertInclude(const cmValueWithOrigin &entry, bool before) @@ -2756,6 +2763,73 @@ void cmTarget::InsertInclude(const cmValueWithOrigin &entry, new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value))); } +//---------------------------------------------------------------------------- +static void processIncludeDirectories(cmTarget *tgt, + const std::vector &entries, + std::vector &includes, + std::set &uniqueIncludes, + cmGeneratorExpressionDAGChecker *dagChecker, + const char *config, bool debugIncludes) +{ + cmMakefile *mf = tgt->GetMakefile(); + + for (std::vector::const_iterator + it = entries.begin(), end = entries.end(); it != end; ++it) + { + bool testIsOff = true; + bool cacheIncludes = false; + std::vector entryIncludes = (*it)->CachedIncludes; + if(!entryIncludes.empty()) + { + testIsOff = false; + } + else + { + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt, + dagChecker), + entryIncludes); + if (mf->IsGeneratingBuildSystem() + && !(*it)->ge->GetHadContextSensitiveCondition()) + { + cacheIncludes = true; + } + } + std::string usedIncludes; + for(std::vector::iterator + li = entryIncludes.begin(); li != entryIncludes.end(); ++li) + { + if (testIsOff && !cmSystemTools::IsOff(li->c_str())) + { + cmSystemTools::ConvertToUnixSlashes(*li); + } + std::string inc = *li; + + if(uniqueIncludes.insert(inc).second) + { + includes.push_back(inc); + if (debugIncludes) + { + usedIncludes += " * " + inc + "\n"; + } + } + } + if (cacheIncludes) + { + (*it)->CachedIncludes = entryIncludes; + } + if (!usedIncludes.empty()) + { + mf->GetCMakeInstance()->IssueMessage(cmake::LOG, + std::string("Used includes for target ") + + tgt->GetName() + ":\n" + + usedIncludes, (*it)->ge->GetBacktrace()); + } + } +} + //---------------------------------------------------------------------------- std::vector cmTarget::GetIncludeDirectories(const char *config) { @@ -2788,63 +2862,50 @@ std::vector cmTarget::GetIncludeDirectories(const char *config) this->DebugIncludesDone = true; } - for (std::vector::const_iterator - it = this->Internal->IncludeDirectoriesEntries.begin(), - end = this->Internal->IncludeDirectoriesEntries.end(); + processIncludeDirectories(this, + this->Internal->IncludeDirectoriesEntries, + includes, + uniqueIncludes, + &dagChecker, + config, + debugIncludes); + + std::vector + linkInterfaceIncludeDirectoriesEntries; + + for (std::vector::const_iterator + it = this->Internal->LinkInterfaceIncludeDirectoriesEntries.begin(), + end = this->Internal->LinkInterfaceIncludeDirectoriesEntries.end(); it != end; ++it) { - - bool testIsOff = true; - bool cacheIncludes = false; - std::vector entryIncludes = (*it)->CachedIncludes; - if(!entryIncludes.empty()) + { + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr cge = ge.Parse(it->Value); + std::string result = cge->Evaluate(this->Makefile, config, + false, this, 0, 0); + if (!this->Makefile->FindTargetToUse(result.c_str())) { - testIsOff = false; - } - else - { - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile, - config, - false, - this, - &dagChecker), - entryIncludes); - if (this->Makefile->IsGeneratingBuildSystem() - && !(*it)->ge->GetHadContextSensitiveCondition()) - { - cacheIncludes = true; - } - } - std::string usedIncludes; - for(std::vector::iterator - li = entryIncludes.begin(); li != entryIncludes.end(); ++li) - { - if (testIsOff && !cmSystemTools::IsOff(li->c_str())) - { - cmSystemTools::ConvertToUnixSlashes(*li); - } - std::string inc = *li; - - if(uniqueIncludes.insert(inc).second) - { - includes.push_back(inc); - if (debugIncludes) - { - usedIncludes += " * " + inc + "\n"; - } - } - } - if (cacheIncludes) - { - (*it)->CachedIncludes = entryIncludes; - } - if (!usedIncludes.empty()) - { - this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, - "Used includes for target " + this->Name + ":\n" - + usedIncludes, (*it)->ge->GetBacktrace()); + continue; } } + cmGeneratorExpression ge(it->Backtrace); + cmsys::auto_ptr cge = ge.Parse( + "$Value + ",INTERFACE_INCLUDE_DIRECTORIES>"); + + linkInterfaceIncludeDirectoriesEntries.push_back( + new cmTargetInternals::IncludeDirectoriesEntry(cge)); + } + + processIncludeDirectories(this, + linkInterfaceIncludeDirectoriesEntries, + includes, + uniqueIncludes, + &dagChecker, + config, + debugIncludes); + + deleteAndClear(linkInterfaceIncludeDirectoriesEntries); + return includes; } @@ -2858,23 +2919,57 @@ std::string cmTarget::GetCompileDefinitions(const char *config) } const char *prop = this->GetProperty(defPropName.c_str()); + cmListFileBacktrace lfbt; + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + defPropName, 0, 0); - if (!prop) + std::string result; + if (prop) { - return ""; + cmGeneratorExpression ge(lfbt); + + result = ge.Parse(prop)->Evaluate(this->Makefile, + config, + false, + this, + &dagChecker); } - cmListFileBacktrace lfbt; - cmGeneratorExpression ge(lfbt); + std::vector libs; + this->GetDirectLinkLibraries(config, libs, this); - cmGeneratorExpressionDAGChecker dagChecker(lfbt, - this->GetName(), - defPropName, 0, 0); - return ge.Parse(prop)->Evaluate(this->Makefile, - config, - false, - this, - &dagChecker); + if (libs.empty()) + { + return result; + } + + std::string sep; + std::string depString; + for (std::vector::const_iterator it = libs.begin(); + it != libs.end(); ++it) + { + if (this->Makefile->FindTargetToUse(it->c_str())) + { + depString += sep + "$"; + sep = ";"; + } + } + + cmGeneratorExpression ge2(lfbt); + cmsys::auto_ptr cge2 = ge2.Parse(depString); + std::string depResult = cge2->Evaluate(this->Makefile, + config, + false, + this, + &dagChecker); + if (!depResult.empty()) + { + result += (result.empty() ? "" : ";") + depResult; + } + + return result; } //---------------------------------------------------------------------------- diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 028a55e537..e659baf1c8 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -495,6 +495,7 @@ public: std::vector GetIncludeDirectories(const char *config); void InsertInclude(const cmValueWithOrigin &entry, bool before = false); + void AppendTllInclude(const cmValueWithOrigin &entry); void AppendBuildInterfaceIncludes(); diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 9dd0e5be27..22ea920287 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -291,6 +291,14 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, // Handle normal case first. if(this->CurrentProcessingState != ProcessingLinkInterface) { + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmValueWithOrigin entry(this->Target->GetDebugGeneratorExpressions(lib, + llt), + lfbt); + this->Target->AppendTllInclude(entry); + } this->Makefile ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt); if (this->CurrentProcessingState != ProcessingPublicInterface)