Fix transitive usage requirements through same-name imported targets

If two imported targets in different directories have the same name we
should still be able to propagate transitive usage requirements from
both.  Fix the DAG checker to work with target pointers instead of
target names since the pointers will not be duplicated even if the names
are.

Fixes: #18345
This commit is contained in:
Brad King
2018-09-06 18:22:31 -04:00
parent 1b57f49586
commit f35be59961
10 changed files with 54 additions and 47 deletions

View File

@@ -108,7 +108,7 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
// build type of the makefile
cmGeneratorExpression ge;
cmGeneratorExpressionDAGChecker dagChecker(
target->GetName(), "INTERFACE_LINK_LIBRARIES", nullptr, nullptr);
target, "INTERFACE_LINK_LIBRARIES", nullptr, nullptr);
std::unique_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(property.second);
std::string evaluated = cge->Evaluate(

View File

@@ -65,8 +65,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
cmGeneratorExpression ge;
cmGeneratorExpressionDAGChecker dagChecker(tgt->GetName(), propName, nullptr,
nullptr);
cmGeneratorExpressionDAGChecker dagChecker(tgt, propName, nullptr, nullptr);
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);

View File

@@ -13,7 +13,6 @@
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorExpressionLexer.h"
#include "cmGeneratorExpressionParser.h"
#include "cmGeneratorTarget.h"
#include "cmSystemTools.h"
cmGeneratorExpression::cmGeneratorExpression(
@@ -395,7 +394,7 @@ const std::string& cmGeneratorExpressionInterpreter::Evaluate(
// Specify COMPILE_OPTIONS to DAGchecker, same semantic as COMPILE_FLAGS
cmGeneratorExpressionDAGChecker dagChecker(
this->HeadTarget->GetName(),
this->HeadTarget,
property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, nullptr,
nullptr);

View File

@@ -14,7 +14,7 @@
#include <utility>
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
const cmListFileBacktrace& backtrace, const std::string& target,
const cmListFileBacktrace& backtrace, cmGeneratorTarget const* target,
const std::string& property, const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent)
: Parent(parent)
@@ -28,7 +28,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
}
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
const std::string& target, const std::string& property,
cmGeneratorTarget const* target, const std::string& property,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent)
: Parent(parent)
@@ -58,8 +58,8 @@ void cmGeneratorExpressionDAGChecker::Initialize()
TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(clang-tidy)
#undef TEST_TRANSITIVE_PROPERTY_METHOD
{
std::map<std::string, std::set<std::string>>::const_iterator it =
top->Seen.find(this->Target);
std::map<cmGeneratorTarget const*, std::set<std::string>>::const_iterator
it = top->Seen.find(this->Target);
if (it != top->Seen.end()) {
const std::set<std::string>& propSet = it->second;
if (propSet.find(this->Property) != propSet.end()) {
@@ -166,7 +166,8 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression()
return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL";
}
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
cmGeneratorTarget const* tgt)
{
const cmGeneratorExpressionDAGChecker* top = this;
const cmGeneratorExpressionDAGChecker* parent = this->Parent;
@@ -189,7 +190,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
}
std::string cmGeneratorExpressionDAGChecker::TopTarget() const
cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const
{
const cmGeneratorExpressionDAGChecker* top = this;
const cmGeneratorExpressionDAGChecker* parent = this->Parent;

View File

@@ -13,6 +13,7 @@
struct GeneratorExpressionContent;
struct cmGeneratorExpressionContext;
class cmGeneratorTarget;
#define CM_SELECT_BOTH(F, A1, A2) F(A1, A2)
#define CM_SELECT_FIRST(F, A1, A2) F(A1)
@@ -41,11 +42,11 @@ struct cmGeneratorExpressionContext;
struct cmGeneratorExpressionDAGChecker
{
cmGeneratorExpressionDAGChecker(const cmListFileBacktrace& backtrace,
const std::string& target,
cmGeneratorTarget const* target,
const std::string& property,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent);
cmGeneratorExpressionDAGChecker(const std::string& target,
cmGeneratorExpressionDAGChecker(cmGeneratorTarget const* target,
const std::string& property,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent);
@@ -64,7 +65,7 @@ struct cmGeneratorExpressionDAGChecker
const std::string& expr);
bool EvaluatingGenexExpression();
bool EvaluatingLinkLibraries(const char* tgt = nullptr);
bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr);
#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
@@ -75,7 +76,7 @@ struct cmGeneratorExpressionDAGChecker
bool GetTransitivePropertiesOnly();
void SetTransitivePropertiesOnly() { this->TransitivePropertiesOnly = true; }
std::string TopTarget() const;
cmGeneratorTarget const* TopTarget() const;
private:
Result CheckGraph() const;
@@ -83,9 +84,9 @@ private:
private:
const cmGeneratorExpressionDAGChecker* const Parent;
const std::string Target;
cmGeneratorTarget const* Target;
const std::string Property;
std::map<std::string, std::set<std::string>> Seen;
std::map<cmGeneratorTarget const*, std::set<std::string>> Seen;
const GeneratorExpressionContent* const Content;
const cmListFileBacktrace Backtrace;
Result CheckResult;

View File

@@ -378,8 +378,8 @@ protected:
{
if (context->HeadTarget) {
cmGeneratorExpressionDAGChecker dagChecker(
context->Backtrace, context->HeadTarget->GetName(), genexOperator,
content, dagCheckerParent);
context->Backtrace, context->HeadTarget, genexOperator, content,
dagCheckerParent);
switch (dagChecker.Check()) {
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: {
@@ -1196,9 +1196,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
return target->GetLinkerLanguage(context->Config);
}
cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
target->GetName(), propertyName,
content, dagCheckerParent);
cmGeneratorExpressionDAGChecker dagChecker(
context->Backtrace, target, propertyName, content, dagCheckerParent);
switch (dagChecker.Check()) {
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
@@ -1911,9 +1910,9 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
return std::string();
}
if (dagChecker &&
(dagChecker->EvaluatingLinkLibraries(name.c_str()) ||
(dagChecker->EvaluatingLinkLibraries(target) ||
(dagChecker->EvaluatingSources() &&
name == dagChecker->TopTarget()))) {
target == dagChecker->TopTarget()))) {
::reportError(context, content->GetOriginalExpression(),
"Expressions which require the linker language may not "
"be used while evaluating link libraries");

View File

@@ -773,7 +773,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(
if (iter == this->SystemIncludesCache.end()) {
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(), "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
@@ -964,8 +964,8 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
this->DebugSourcesDone = true;
}
cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "SOURCES",
nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr,
nullptr);
std::unordered_set<std::string> uniqueSrcs;
bool contextDependentDirectSources =
@@ -2078,8 +2078,8 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
}
cmGeneratorExpression ge;
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(), "AUTOUIC_OPTIONS", nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr,
nullptr);
cmSystemTools::ExpandListArgument(
ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, this,
&dagChecker),
@@ -2588,8 +2588,8 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
std::vector<std::string> includes;
std::unordered_set<std::string> uniqueIncludes;
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(), "INCLUDE_DIRECTORIES", nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES",
nullptr, nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
@@ -2710,8 +2710,8 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
{
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(), "COMPILE_OPTIONS", nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr,
nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
@@ -2763,8 +2763,8 @@ void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
{
std::unordered_set<std::string> uniqueFeatures;
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(), "COMPILE_FEATURES", nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr,
nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
@@ -2814,8 +2814,8 @@ void cmGeneratorTarget::GetCompileDefinitions(
{
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(), "COMPILE_DEFINITIONS", nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS",
nullptr, nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
@@ -2895,8 +2895,8 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
{
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "LINK_OPTIONS",
nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr,
nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
@@ -3043,8 +3043,8 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions(
std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries;
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(), "STATIC_LIBRARY_OPTIONS", nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS",
nullptr, nullptr);
if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
std::vector<std::string> options;
@@ -3083,8 +3083,8 @@ void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
{
std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries;
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "LINK_DEPENDS",
nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
nullptr);
if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) {
std::vector<std::string> depends;
@@ -4509,8 +4509,7 @@ void cmGeneratorTarget::ExpandLinkItems(
std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const
{
cmGeneratorExpression ge;
cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, nullptr,
nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr);
// The $<LINK_ONLY> expression may be in a link interface to specify private
// link dependencies that are otherwise excluded from usage requirements.
if (usage_requirements_only) {
@@ -5561,8 +5560,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
end = entryRange.end();
le != end; ++le, ++btIt) {
std::vector<std::string> llibs;
cmGeneratorExpressionDAGChecker dagChecker(
this->GetName(), "LINK_LIBRARIES", nullptr, nullptr);
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr,
nullptr);
cmGeneratorExpression ge(*btIt);
std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
std::string const& evaluated =

View File

@@ -1,4 +1,5 @@
add_library(a STATIC a.c)
target_compile_definitions(a INTERFACE DEF_A)
add_library(sameName INTERFACE IMPORTED)
target_link_libraries(sameName INTERFACE a)

View File

@@ -1,4 +1,5 @@
add_library(b STATIC b.c)
target_compile_definitions(b INTERFACE DEF_B)
add_library(sameName INTERFACE IMPORTED)
target_link_libraries(sameName INTERFACE b)

View File

@@ -1,3 +1,10 @@
#ifndef DEF_A
# error "DEF_A not defined"
#endif
#ifndef DEF_B
# error "DEF_B not defined"
#endif
extern void a(void);
extern void b(void);