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());
|
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 (!prop)
|
||||||
{
|
{
|
||||||
if (target->IsImported())
|
if (target->IsImported())
|
||||||
{
|
{
|
||||||
return std::string();
|
return linkedTargetsContent;
|
||||||
}
|
|
||||||
if (dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
|
|
||||||
{
|
|
||||||
return std::string();
|
|
||||||
}
|
}
|
||||||
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
|
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
|
||||||
context->Config))
|
context->Config))
|
||||||
|
@ -480,7 +533,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
return propContent ? propContent : "";
|
return propContent ? propContent : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string();
|
return linkedTargetsContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0;
|
for (size_t i = 0;
|
||||||
|
@ -503,6 +556,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
{
|
{
|
||||||
context->HadContextSensitiveCondition = true;
|
context->HadContextSensitiveCondition = true;
|
||||||
}
|
}
|
||||||
|
if (!linkedTargetsContent.empty())
|
||||||
|
{
|
||||||
|
result += (result.empty() ? "" : ";") + linkedTargetsContent;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,7 @@ public:
|
||||||
std::vector<std::string> CachedIncludes;
|
std::vector<std::string> CachedIncludes;
|
||||||
};
|
};
|
||||||
std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
|
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,
|
void cmTarget::InsertInclude(const cmValueWithOrigin &entry,
|
||||||
bool before)
|
bool before)
|
||||||
|
@ -2756,6 +2763,73 @@ void cmTarget::InsertInclude(const cmValueWithOrigin &entry,
|
||||||
new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value)));
|
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)
|
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;
|
this->DebugIncludesDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
|
processIncludeDirectories(this,
|
||||||
it = this->Internal->IncludeDirectoriesEntries.begin(),
|
this->Internal->IncludeDirectoriesEntries,
|
||||||
end = this->Internal->IncludeDirectoriesEntries.end();
|
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)
|
it != end; ++it)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
bool testIsOff = true;
|
cmGeneratorExpression ge(lfbt);
|
||||||
bool cacheIncludes = false;
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(it->Value);
|
||||||
std::vector<std::string> entryIncludes = (*it)->CachedIncludes;
|
std::string result = cge->Evaluate(this->Makefile, config,
|
||||||
if(!entryIncludes.empty())
|
false, this, 0, 0);
|
||||||
|
if (!this->Makefile->FindTargetToUse(result.c_str()))
|
||||||
{
|
{
|
||||||
testIsOff = false;
|
continue;
|
||||||
}
|
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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;
|
return includes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2858,23 +2919,57 @@ std::string cmTarget::GetCompileDefinitions(const char *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *prop = this->GetProperty(defPropName.c_str());
|
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;
|
std::vector<std::string> libs;
|
||||||
cmGeneratorExpression ge(lfbt);
|
this->GetDirectLinkLibraries(config, libs, this);
|
||||||
|
|
||||||
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
|
if (libs.empty())
|
||||||
this->GetName(),
|
{
|
||||||
defPropName, 0, 0);
|
return result;
|
||||||
return ge.Parse(prop)->Evaluate(this->Makefile,
|
}
|
||||||
config,
|
|
||||||
false,
|
std::string sep;
|
||||||
this,
|
std::string depString;
|
||||||
&dagChecker);
|
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);
|
std::vector<std::string> GetIncludeDirectories(const char *config);
|
||||||
void InsertInclude(const cmValueWithOrigin &entry,
|
void InsertInclude(const cmValueWithOrigin &entry,
|
||||||
bool before = false);
|
bool before = false);
|
||||||
|
void AppendTllInclude(const cmValueWithOrigin &entry);
|
||||||
|
|
||||||
void AppendBuildInterfaceIncludes();
|
void AppendBuildInterfaceIncludes();
|
||||||
|
|
||||||
|
|
|
@ -291,6 +291,14 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
|
||||||
// Handle normal case first.
|
// Handle normal case first.
|
||||||
if(this->CurrentProcessingState != ProcessingLinkInterface)
|
if(this->CurrentProcessingState != ProcessingLinkInterface)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
cmListFileBacktrace lfbt;
|
||||||
|
this->Makefile->GetBacktrace(lfbt);
|
||||||
|
cmValueWithOrigin entry(this->Target->GetDebugGeneratorExpressions(lib,
|
||||||
|
llt),
|
||||||
|
lfbt);
|
||||||
|
this->Target->AppendTllInclude(entry);
|
||||||
|
}
|
||||||
this->Makefile
|
this->Makefile
|
||||||
->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
|
->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
|
||||||
if (this->CurrentProcessingState != ProcessingPublicInterface)
|
if (this->CurrentProcessingState != ProcessingPublicInterface)
|
||||||
|
|
Loading…
Reference in New Issue