Expand includes and defines transitively in 'external' genexes.
This means that we can use expressions of the form $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> to get a list of the interface include directories of foo, including those coming from dependencies. We can't have a test of a target which has a single include directory in its INCLUDE_DIRECTORIES because the shell on the MSYS platforms transforms a single include directory to include a prefix, which is not what the test expects. We test a target with two directories instead as a means to test a target with no link dependencies.
This commit is contained in:
parent
d1a2729b1a
commit
7e707444be
|
@ -452,8 +452,6 @@ 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)
|
||||||
{
|
{
|
||||||
if (dagCheckerParent->EvaluatingLinkLibraries())
|
if (dagCheckerParent->EvaluatingLinkLibraries())
|
||||||
|
@ -467,17 +465,28 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
{
|
{
|
||||||
assert(dagCheckerParent->EvaluatingIncludeDirectories()
|
assert(dagCheckerParent->EvaluatingIncludeDirectories()
|
||||||
|| dagCheckerParent->EvaluatingCompileDefinitions());
|
|| dagCheckerParent->EvaluatingCompileDefinitions());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string linkedTargetsContent;
|
||||||
|
|
||||||
|
std::string interfacePropertyName;
|
||||||
|
|
||||||
if (propertyName == "INTERFACE_INCLUDE_DIRECTORIES"
|
if (propertyName == "INTERFACE_INCLUDE_DIRECTORIES"
|
||||||
|| propertyName == "INTERFACE_COMPILE_DEFINITIONS")
|
|| propertyName == "INCLUDE_DIRECTORIES")
|
||||||
{
|
{
|
||||||
if (*it == target->GetName())
|
interfacePropertyName = "INTERFACE_INCLUDE_DIRECTORIES";
|
||||||
{
|
|
||||||
// Broken code can have a target in its own link interface.
|
|
||||||
// Don't follow such link interface entries so as not to create a
|
|
||||||
// self-referencing loop.
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
else if (propertyName == "INTERFACE_COMPILE_DEFINITIONS"
|
||||||
|
|| propertyName == "COMPILE_DEFINITIONS"
|
||||||
|
|| strncmp(propertyName.c_str(), "COMPILE_DEFINITIONS_", 20) == 0)
|
||||||
|
{
|
||||||
|
interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interfacePropertyName == "INTERFACE_INCLUDE_DIRECTORIES"
|
||||||
|
|| interfacePropertyName == "INTERFACE_COMPILE_DEFINITIONS")
|
||||||
|
{
|
||||||
const cmTarget::LinkInterface *iface = target->GetLinkInterface(
|
const cmTarget::LinkInterface *iface = target->GetLinkInterface(
|
||||||
context->Config,
|
context->Config,
|
||||||
context->HeadTarget);
|
context->HeadTarget);
|
||||||
|
@ -491,10 +500,18 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
it = iface->Libraries.begin();
|
it = iface->Libraries.begin();
|
||||||
it != iface->Libraries.end(); ++it)
|
it != iface->Libraries.end(); ++it)
|
||||||
{
|
{
|
||||||
|
if (*it == target->GetName())
|
||||||
|
{
|
||||||
|
// Broken code can have a target in its own link interface.
|
||||||
|
// Don't follow such link interface entries so as not to create a
|
||||||
|
// self-referencing loop.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (context->Makefile->FindTargetToUse(it->c_str()))
|
if (context->Makefile->FindTargetToUse(it->c_str()))
|
||||||
{
|
{
|
||||||
depString +=
|
depString +=
|
||||||
sep + "$<TARGET_PROPERTY:" + *it + "," + propertyName + ">";
|
sep + "$<TARGET_PROPERTY:" + *it + ","
|
||||||
|
+ interfacePropertyName + ">";
|
||||||
sep = ";";
|
sep = ";";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -512,8 +529,6 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedTargetsContent =
|
linkedTargetsContent =
|
||||||
cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
|
cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
|
||||||
|
@ -551,7 +566,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
sizeof(*targetPropertyTransitiveWhitelist));
|
sizeof(*targetPropertyTransitiveWhitelist));
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
if (targetPropertyTransitiveWhitelist[i] == propertyName)
|
if (targetPropertyTransitiveWhitelist[i] == interfacePropertyName)
|
||||||
{
|
{
|
||||||
cmGeneratorExpression ge(context->Backtrace);
|
cmGeneratorExpression ge(context->Backtrace);
|
||||||
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required (VERSION 2.8.8)
|
cmake_minimum_required (VERSION 2.8.8)
|
||||||
project(GeneratorExpression NONE)
|
project(GeneratorExpression CXX)
|
||||||
|
|
||||||
add_custom_target(check-part1 ALL
|
add_custom_target(check-part1 ALL
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
@ -62,6 +62,27 @@ add_custom_target(check-part1 ALL
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_library(empty1 empty.cpp)
|
||||||
|
target_include_directories(empty1 PUBLIC /empty1/public)
|
||||||
|
target_include_directories(empty1 PRIVATE /empty1/private)
|
||||||
|
|
||||||
|
add_library(empty2 empty.cpp)
|
||||||
|
target_include_directories(empty2 PUBLIC /empty2/public)
|
||||||
|
|
||||||
|
add_library(empty3 empty.cpp)
|
||||||
|
target_include_directories(empty3 PUBLIC /empty3/public)
|
||||||
|
target_include_directories(empty3 PRIVATE /empty3/private)
|
||||||
|
|
||||||
|
add_library(empty4 empty.cpp)
|
||||||
|
target_include_directories(empty4 PUBLIC /empty4/public)
|
||||||
|
|
||||||
|
target_link_libraries(empty1 LINK_PUBLIC empty2)
|
||||||
|
target_link_libraries(empty2 LINK_PUBLIC empty3 empty4)
|
||||||
|
target_link_libraries(empty3 LINK_PUBLIC empty2 empty4)
|
||||||
|
|
||||||
|
add_library(empty5 empty.cpp)
|
||||||
|
target_include_directories(empty5 PRIVATE /empty5/private1 /empty5/private2)
|
||||||
|
|
||||||
add_custom_target(check-part2 ALL
|
add_custom_target(check-part2 ALL
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-Dtest_incomplete_1=$<
|
-Dtest_incomplete_1=$<
|
||||||
|
@ -89,6 +110,14 @@ add_custom_target(check-part2 ALL
|
||||||
-Dtest_install_interface=$<INSTALL_INTERFACE:install>
|
-Dtest_install_interface=$<INSTALL_INTERFACE:install>
|
||||||
-Dtest_target_name_1=$<TARGET_NAME:tgt,ok>
|
-Dtest_target_name_1=$<TARGET_NAME:tgt,ok>
|
||||||
-Dtest_target_name_2=$<TARGET_NAME:tgt:ok>
|
-Dtest_target_name_2=$<TARGET_NAME:tgt:ok>
|
||||||
|
-Dtest_target_includes1=$<TARGET_PROPERTY:empty1,INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
|
-Dtest_target_includes2=$<TARGET_PROPERTY:empty2,INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
|
-Dtest_target_includes3=$<TARGET_PROPERTY:empty3,INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
|
-Dtest_target_includes4=$<TARGET_PROPERTY:empty1,INCLUDE_DIRECTORIES>
|
||||||
|
-Dtest_target_includes5=$<TARGET_PROPERTY:empty2,INCLUDE_DIRECTORIES>
|
||||||
|
-Dtest_target_includes6=$<TARGET_PROPERTY:empty3,INCLUDE_DIRECTORIES>
|
||||||
|
-Dtest_target_includes7=$<TARGET_PROPERTY:empty1,INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
|
-Dtest_target_includes8=$<TARGET_PROPERTY:empty5,INCLUDE_DIRECTORIES>
|
||||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)"
|
COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)"
|
||||||
VERBATIM
|
VERBATIM
|
||||||
|
|
|
@ -26,3 +26,11 @@ check(test_build_interface "build")
|
||||||
check(test_install_interface "")
|
check(test_install_interface "")
|
||||||
check(test_target_name_1 "tgt,ok")
|
check(test_target_name_1 "tgt,ok")
|
||||||
check(test_target_name_2 "tgt:ok")
|
check(test_target_name_2 "tgt:ok")
|
||||||
|
check(test_target_includes1 "/empty1/public;/empty2/public;/empty3/public;/empty4/public;/empty4/public")
|
||||||
|
check(test_target_includes2 "/empty2/public;/empty3/public;/empty4/public;/empty4/public")
|
||||||
|
check(test_target_includes3 "/empty3/public;/empty2/public;/empty4/public;/empty4/public")
|
||||||
|
check(test_target_includes4 "/empty1/public;/empty1/private;/empty2/public;/empty3/public;/empty4/public")
|
||||||
|
check(test_target_includes5 "/empty2/public;/empty3/public;/empty2/public;/empty4/public")
|
||||||
|
check(test_target_includes6 "/empty3/public;/empty3/private;/empty2/public;/empty3/public;/empty4/public")
|
||||||
|
check(test_target_includes7 "/empty1/public;/empty2/public;/empty3/public;/empty4/public;/empty4/public")
|
||||||
|
check(test_target_includes8 "/empty5/private1;/empty5/private2")
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
// empty
|
Loading…
Reference in New Issue