From 79edd00235091475d5b3f1305bcf991cad3e45f4 Mon Sep 17 00:00:00 2001
From: Stephen Kelly <steveire@gmail.com>
Date: Mon, 15 Oct 2012 10:27:42 +0200
Subject: [PATCH] GenEx: Fix reporting about not-found include directories and
 libraries.

This fixes a regression introduced in commit 290e92ad (Move
GetIncludeDirectories to cmGeneratorTarget, 2012-09-16) which loops over
cmGeneratorTargets before they get created, so the container is empty.
---
 Source/cmGeneratorExpression.cxx              | 49 +++++++++++++++++++
 Source/cmGeneratorExpression.h                |  7 +++
 Source/cmGlobalGenerator.cxx                  | 22 ++++++---
 Source/cmMakeDepend.cxx                       | 19 +++++--
 Tests/RunCMake/CMakeLists.txt                 |  1 +
 .../include_directories/CMakeLists.txt        |  3 ++
 .../NotFoundContent-result.txt                |  1 +
 .../NotFoundContent-stderr.txt                |  6 +++
 .../include_directories/NotFoundContent.cmake |  9 ++++
 .../include_directories/RunCMakeTest.cmake    |  3 ++
 10 files changed, 110 insertions(+), 10 deletions(-)
 create mode 100644 Tests/RunCMake/include_directories/CMakeLists.txt
 create mode 100644 Tests/RunCMake/include_directories/NotFoundContent-result.txt
 create mode 100644 Tests/RunCMake/include_directories/NotFoundContent-stderr.txt
 create mode 100644 Tests/RunCMake/include_directories/NotFoundContent.cmake
 create mode 100644 Tests/RunCMake/include_directories/RunCMakeTest.cmake

diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 3f8e962be5..7d8df37333 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -13,6 +13,7 @@
 
 #include "cmMakefile.h"
 #include "cmTarget.h"
+#include "assert.h"
 
 #include <cmsys/String.h>
 
@@ -129,3 +130,51 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
     delete *it;
     }
 }
+
+std::string cmGeneratorExpression::Preprocess(const std::string &input,
+                                              PreprocessContext context)
+{
+  if (context != StripAllGeneratorExpressions)
+  {
+    assert(!"cmGeneratorExpression::Preprocess called with invalid args");
+    return std::string();
+  }
+
+  std::string result;
+  std::string::size_type pos = 0;
+  std::string::size_type lastPos = pos;
+  while((pos = input.find("$<", lastPos)) != input.npos)
+    {
+    result += input.substr(lastPos, pos - lastPos);
+    pos += 2;
+    int nestingLevel = 1;
+    const char *c = input.c_str() + pos;
+    const char * const cStart = c;
+    for ( ; *c; ++c)
+      {
+      if(c[0] == '$' && c[1] == '<')
+        {
+        ++nestingLevel;
+        ++c;
+        continue;
+        }
+      if(c[0] == '>')
+        {
+        --nestingLevel;
+        if (nestingLevel == 0)
+          {
+          break;
+          }
+        }
+      }
+    const std::string::size_type traversed = (c - cStart) + 1;
+    if (!*c)
+      {
+      result += "$<" + input.substr(pos, traversed);
+      }
+    pos += traversed;
+    lastPos = pos;
+    }
+  result += input.substr(lastPos);
+  return result;
+}
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index d37ce97d3b..29d3f444f6 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -48,6 +48,13 @@ public:
   const cmCompiledGeneratorExpression& Parse(std::string const& input);
   const cmCompiledGeneratorExpression& Parse(const char* input);
 
+  enum PreprocessContext {
+    StripAllGeneratorExpressions
+  };
+
+  static std::string Preprocess(const std::string &input,
+                                PreprocessContext context);
+
 private:
   cmGeneratorExpression(const cmGeneratorExpression &);
   void operator=(const cmGeneratorExpression &);
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 09588f9837..23ec08a2de 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -25,6 +25,7 @@
 #include "cmComputeTargetDepends.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
+#include "cmGeneratorExpression.h"
 
 #include <cmsys/Directory.hxx>
 
@@ -1152,13 +1153,13 @@ void cmGlobalGenerator::CheckLocalGenerators()
     {
     manager = this->LocalGenerators[i]->GetMakefile()->GetCacheManager();
     this->LocalGenerators[i]->ConfigureFinalPass();
-    cmGeneratorTargetsType targets =
-      this->LocalGenerators[i]->GetMakefile()->GetGeneratorTargets();
-    for (cmGeneratorTargetsType::iterator l = targets.begin();
+    cmTargets &targets =
+      this->LocalGenerators[i]->GetMakefile()->GetTargets();
+    for (cmTargets::iterator l = targets.begin();
          l != targets.end(); l++)
       {
       const cmTarget::LinkLibraryVectorType& libs =
-        l->second->Target->GetOriginalLinkLibraries();
+        l->second.GetOriginalLinkLibraries();
       for(cmTarget::LinkLibraryVectorType::const_iterator lib = libs.begin();
           lib != libs.end(); ++lib)
         {
@@ -1174,14 +1175,23 @@ void cmGlobalGenerator::CheckLocalGenerators()
             }
           std::string text = notFoundMap[varName];
           text += "\n    linked by target \"";
-          text += l->second->GetName();
+          text += l->second.GetName();
           text += "\" in directory ";
           text+=this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
           notFoundMap[varName] = text;
           }
         }
       std::vector<std::string> incs;
-      this->LocalGenerators[i]->GetIncludeDirectories(incs, l->second);
+      const char *incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES");
+      if (!incDirProp)
+        {
+        continue;
+        }
+
+      std::string incDirs = cmGeneratorExpression::Preprocess(incDirProp,
+                        cmGeneratorExpression::StripAllGeneratorExpressions);
+
+      cmSystemTools::ExpandListArgument(incDirs.c_str(), incs);
 
       for( std::vector<std::string>::const_iterator incDir = incs.begin();
             incDir != incs.end(); ++incDir)
diff --git a/Source/cmMakeDepend.cxx b/Source/cmMakeDepend.cxx
index 75a76a42e2..2ae35ef140 100644
--- a/Source/cmMakeDepend.cxx
+++ b/Source/cmMakeDepend.cxx
@@ -11,6 +11,7 @@
 ============================================================================*/
 #include "cmMakeDepend.h"
 #include "cmSystemTools.h"
+#include "cmGeneratorExpression.h"
 
 #include <cmsys/RegularExpression.hxx>
 
@@ -58,12 +59,22 @@ void cmMakeDepend::SetMakefile(cmMakefile* makefile)
   // Now extract any include paths from the targets
   std::set<std::string> uniqueIncludes;
   std::vector<std::string> orderedAndUniqueIncludes;
-  cmGeneratorTargetsType targets = this->Makefile->GetGeneratorTargets();
-  for (cmGeneratorTargetsType::iterator l = targets.begin();
+  cmTargets &targets = this->Makefile->GetTargets();
+  for (cmTargets::iterator l = targets.begin();
        l != targets.end(); ++l)
     {
-    const std::vector<std::string>& includes =
-      l->second->GetIncludeDirectories();
+    const char *incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES");
+    if (!incDirProp)
+      {
+      continue;
+      }
+
+    std::string incDirs = cmGeneratorExpression::Preprocess(incDirProp,
+                      cmGeneratorExpression::StripAllGeneratorExpressions);
+
+    std::vector<std::string> includes;
+    cmSystemTools::ExpandListArgument(incDirs.c_str(), includes);
+
     for(std::vector<std::string>::const_iterator j = includes.begin();
         j != includes.end(); ++j)
       {
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 2fa7141703..8c67625ffc 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -53,6 +53,7 @@ add_RunCMake_test(ObjectLibrary)
 add_RunCMake_test(build_command)
 add_RunCMake_test(find_package)
 add_RunCMake_test(include)
+add_RunCMake_test(include_directories)
 add_RunCMake_test(list)
 
 if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]")
diff --git a/Tests/RunCMake/include_directories/CMakeLists.txt b/Tests/RunCMake/include_directories/CMakeLists.txt
new file mode 100644
index 0000000000..e8db6b05be
--- /dev/null
+++ b/Tests/RunCMake/include_directories/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/include_directories/NotFoundContent-result.txt b/Tests/RunCMake/include_directories/NotFoundContent-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/include_directories/NotFoundContent-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/include_directories/NotFoundContent-stderr.txt b/Tests/RunCMake/include_directories/NotFoundContent-stderr.txt
new file mode 100644
index 0000000000..f608d633fe
--- /dev/null
+++ b/Tests/RunCMake/include_directories/NotFoundContent-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
+Please set them or make sure they are set and tested correctly in the CMake files:
+NotThere1
+   used as include directory in directory .*
+NotThere2
+   used as include directory in directory .*
diff --git a/Tests/RunCMake/include_directories/NotFoundContent.cmake b/Tests/RunCMake/include_directories/NotFoundContent.cmake
new file mode 100644
index 0000000000..9677e0c43a
--- /dev/null
+++ b/Tests/RunCMake/include_directories/NotFoundContent.cmake
@@ -0,0 +1,9 @@
+
+include_directories(NotThere1-NOTFOUND)
+
+include_directories($<1:There1-NOTFOUND>)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp" "int main(int,char**) { return 0; }\n")
+add_executable(dummy "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp")
+set_property(TARGET dummy APPEND PROPERTY INCLUDE_DIRECTORIES "NotThere2-NOTFOUND")
+set_property(TARGET dummy APPEND PROPERTY INCLUDE_DIRECTORIES "$<1:There2-NOTFOUND>")
diff --git a/Tests/RunCMake/include_directories/RunCMakeTest.cmake b/Tests/RunCMake/include_directories/RunCMakeTest.cmake
new file mode 100644
index 0000000000..aee3f799b0
--- /dev/null
+++ b/Tests/RunCMake/include_directories/RunCMakeTest.cmake
@@ -0,0 +1,3 @@
+include(RunCMake)
+
+run_cmake(NotFoundContent)
-- 
GitLab