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 $<TARGET_PROPERTY:bar,INTERFACE_INCLUDE_DIRECTORIES>) 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.
This commit is contained in:
parent
5c9f5e313f
commit
a1c4905f72
|
@ -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<std::string>::const_iterator
|
||||
it = iface->Libraries.begin();
|
||||
it != iface->Libraries.end(); ++it)
|
||||
{
|
||||
if (context->Makefile->FindTargetToUse(it->c_str()))
|
||||
{
|
||||
depString +=
|
||||
sep + "$<TARGET_PROPERTY:" + *it + "," + propertyName + ">";
|
||||
sep = ";";
|
||||
}
|
||||
}
|
||||
cmsys::auto_ptr<cmCompiledGeneratorExpression> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,6 +137,7 @@ public:
|
|||
std::vector<std::string> CachedIncludes;
|
||||
};
|
||||
std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
|
||||
std::vector<cmValueWithOrigin> 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<cmTargetInternals::IncludeDirectoriesEntry*> &entries,
|
||||
std::vector<std::string> &includes,
|
||||
std::set<std::string> &uniqueIncludes,
|
||||
cmGeneratorExpressionDAGChecker *dagChecker,
|
||||
const char *config, bool debugIncludes)
|
||||
{
|
||||
cmMakefile *mf = tgt->GetMakefile();
|
||||
|
||||
for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
|
||||
it = entries.begin(), end = entries.end(); it != end; ++it)
|
||||
{
|
||||
bool testIsOff = true;
|
||||
bool cacheIncludes = false;
|
||||
std::vector<std::string> 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<std::string>::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<std::string> cmTarget::GetIncludeDirectories(const char *config)
|
||||
{
|
||||
|
@ -2788,63 +2862,50 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
|
|||
this->DebugIncludesDone = true;
|
||||
}
|
||||
|
||||
for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
|
||||
it = this->Internal->IncludeDirectoriesEntries.begin(),
|
||||
end = this->Internal->IncludeDirectoriesEntries.end();
|
||||
processIncludeDirectories(this,
|
||||
this->Internal->IncludeDirectoriesEntries,
|
||||
includes,
|
||||
uniqueIncludes,
|
||||
&dagChecker,
|
||||
config,
|
||||
debugIncludes);
|
||||
|
||||
std::vector<cmTargetInternals::IncludeDirectoriesEntry*>
|
||||
linkInterfaceIncludeDirectoriesEntries;
|
||||
|
||||
for (std::vector<cmValueWithOrigin>::const_iterator
|
||||
it = this->Internal->LinkInterfaceIncludeDirectoriesEntries.begin(),
|
||||
end = this->Internal->LinkInterfaceIncludeDirectoriesEntries.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
|
||||
bool testIsOff = true;
|
||||
bool cacheIncludes = false;
|
||||
std::vector<std::string> entryIncludes = (*it)->CachedIncludes;
|
||||
if(!entryIncludes.empty())
|
||||
{
|
||||
cmGeneratorExpression ge(lfbt);
|
||||
cmsys::auto_ptr<cmCompiledGeneratorExpression> 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<std::string>::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<cmCompiledGeneratorExpression> cge = ge.Parse(
|
||||
"$<TARGET_PROPERTY:" + it->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<std::string> 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<std::string>::const_iterator it = libs.begin();
|
||||
it != libs.end(); ++it)
|
||||
{
|
||||
if (this->Makefile->FindTargetToUse(it->c_str()))
|
||||
{
|
||||
depString += sep + "$<TARGET_PROPERTY:"
|
||||
+ *it + ",INTERFACE_COMPILE_DEFINITIONS>";
|
||||
sep = ";";
|
||||
}
|
||||
}
|
||||
|
||||
cmGeneratorExpression ge2(lfbt);
|
||||
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge2 = ge2.Parse(depString);
|
||||
std::string depResult = cge2->Evaluate(this->Makefile,
|
||||
config,
|
||||
false,
|
||||
this,
|
||||
&dagChecker);
|
||||
if (!depResult.empty())
|
||||
{
|
||||
result += (result.empty() ? "" : ";") + depResult;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
@ -495,6 +495,7 @@ public:
|
|||
std::vector<std::string> GetIncludeDirectories(const char *config);
|
||||
void InsertInclude(const cmValueWithOrigin &entry,
|
||||
bool before = false);
|
||||
void AppendTllInclude(const cmValueWithOrigin &entry);
|
||||
|
||||
void AppendBuildInterfaceIncludes();
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue