Ver código fonte

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.
Stephen Kelly 13 anos atrás
pai
commit
7e707444be

+ 51 - 36
Source/cmGeneratorExpressionEvaluator.cxx

@@ -452,8 +452,6 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 
     const char *prop = target->GetProperty(propertyName.c_str());
 
-    std::string linkedTargetsContent;
-
     if (dagCheckerParent)
       {
       if (dagCheckerParent->EvaluatingLinkLibraries())
@@ -467,9 +465,40 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
         {
         assert(dagCheckerParent->EvaluatingIncludeDirectories()
             || dagCheckerParent->EvaluatingCompileDefinitions());
+        }
+      }
+
+    std::string linkedTargetsContent;
+
+    std::string interfacePropertyName;
 
-        if (propertyName == "INTERFACE_INCLUDE_DIRECTORIES"
-            || propertyName == "INTERFACE_COMPILE_DEFINITIONS")
+    if (propertyName == "INTERFACE_INCLUDE_DIRECTORIES"
+        || propertyName == "INCLUDE_DIRECTORIES")
+      {
+      interfacePropertyName = "INTERFACE_INCLUDE_DIRECTORIES";
+      }
+    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(
+                                                    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 (*it == target->GetName())
             {
@@ -478,40 +507,26 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
             // self-referencing loop.
             continue;
             }
-          const cmTarget::LinkInterface *iface = target->GetLinkInterface(
-                                                        context->Config,
-                                                        context->HeadTarget);
-          if(iface)
+          if (context->Makefile->FindTargetToUse(it->c_str()))
             {
-            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;
-              }
+            depString +=
+              sep + "$<TARGET_PROPERTY:" + *it + ","
+                                         + interfacePropertyName + ">";
+            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;
+          }
         }
       }
 
@@ -551,7 +566,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
               sizeof(*targetPropertyTransitiveWhitelist));
          ++i)
       {
-      if (targetPropertyTransitiveWhitelist[i] == propertyName)
+      if (targetPropertyTransitiveWhitelist[i] == interfacePropertyName)
         {
         cmGeneratorExpression ge(context->Backtrace);
         cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);

+ 30 - 1
Tests/GeneratorExpression/CMakeLists.txt

@@ -1,5 +1,5 @@
 cmake_minimum_required (VERSION 2.8.8)
-project(GeneratorExpression NONE)
+project(GeneratorExpression CXX)
 
 add_custom_target(check-part1 ALL
   COMMAND ${CMAKE_COMMAND}
@@ -62,6 +62,27 @@ add_custom_target(check-part1 ALL
   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
   COMMAND ${CMAKE_COMMAND}
     -Dtest_incomplete_1=$<
@@ -89,6 +110,14 @@ add_custom_target(check-part2 ALL
     -Dtest_install_interface=$<INSTALL_INTERFACE:install>
     -Dtest_target_name_1=$<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
   COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)"
   VERBATIM

+ 8 - 0
Tests/GeneratorExpression/check-part2.cmake

@@ -26,3 +26,11 @@ check(test_build_interface "build")
 check(test_install_interface "")
 check(test_target_name_1 "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")

+ 2 - 0
Tests/GeneratorExpression/empty.cpp

@@ -0,0 +1,2 @@
+
+// empty