ソースを参照

Keep track of INCLUDE_DIRECTORIES as a vector of structs.

The struct can keep track of where the include came from, which gives
us proper backtraces.
Stephen Kelly 13 年 前
コミット
18a3195ad5

+ 1 - 39
Source/cmGeneratorTarget.cxx

@@ -252,45 +252,7 @@ const char* cmGeneratorTarget::GetCreateRuleVariable()
 std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
                                                           const char *config)
 {
-  std::vector<std::string> includes;
-  const char *prop = this->Target->GetProperty("INCLUDE_DIRECTORIES");
-  if(!prop)
-    {
-    return includes;
-    }
-
-  cmListFileBacktrace lfbt;
-  cmGeneratorExpression ge(lfbt);
-
-  cmGeneratorExpressionDAGChecker dagChecker(lfbt,
-                                              this->GetName(),
-                                              "INCLUDE_DIRECTORIES", 0, 0);
-
-  cmSystemTools::ExpandListArgument(ge.Parse(prop)
-                                    ->Evaluate(this->Makefile,
-                                              config,
-                                              false,
-                                              this->Target,
-                                              &dagChecker),
-                                    includes);
-
-  std::set<std::string> uniqueIncludes;
-  std::vector<std::string> orderedAndUniqueIncludes;
-  for(std::vector<std::string>::const_iterator
-      li = includes.begin(); li != includes.end(); ++li)
-    {
-    std::string inc = *li;
-    if (!cmSystemTools::IsOff(inc.c_str()))
-      {
-      cmSystemTools::ConvertToUnixSlashes(inc);
-      }
-    if(uniqueIncludes.insert(inc).second)
-      {
-      orderedAndUniqueIncludes.push_back(inc);
-      }
-    }
-
-  return orderedAndUniqueIncludes;
+  return this->Target->GetIncludeDirectories(config);
 }
 
 //----------------------------------------------------------------------------

+ 46 - 44
Source/cmMakefile.cxx

@@ -1485,9 +1485,12 @@ void cmMakefile::InitializeFromParent()
   // Initialize definitions with the closure of the parent scope.
   this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure();
 
-  // copy include paths
-  this->SetProperty("INCLUDE_DIRECTORIES",
-                    parent->GetProperty("INCLUDE_DIRECTORIES"));
+  const std::vector<IncludeDirectoriesEntry> parentIncludes =
+                                        parent->GetIncludeDirectoriesEntries();
+  this->IncludeDirectoriesEntries.insert(this->IncludeDirectoriesEntries.end(),
+                                       parentIncludes.begin(),
+                                       parentIncludes.end());
+
   this->SystemIncludeDirectories = parent->SystemIncludeDirectories;
 
   // define flags
@@ -1612,41 +1615,6 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath,
     }
 }
 
-//----------------------------------------------------------------------------
-void AddStringToProperty(cmProperty *prop, const char* name, const char* s,
-                         bool before)
-{
-  if (!prop)
-    {
-    return;
-    }
-
-  // Don't worry about duplicates at this point. We eliminate them when
-  // we convert the property to a vector in GetIncludeDirectories.
-
-  if (before)
-    {
-    const char *val = prop->GetValue();
-    cmOStringStream oss;
-
-    if(val && *val)
-      {
-      oss << s << ";" << val;
-      }
-    else
-      {
-      oss << s;
-      }
-
-    std::string newVal = oss.str();
-    prop->Set(name, newVal.c_str());
-    }
-  else
-    {
-    prop->Append(name, s);
-    }
-}
-
 //----------------------------------------------------------------------------
 void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
 {
@@ -1655,18 +1623,21 @@ void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
     return;
     }
 
-  // Directory property:
-  cmProperty *prop =
-    this->GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES");
-  AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before);
+  std::vector<IncludeDirectoriesEntry>::iterator position =
+                               before ? this->IncludeDirectoriesEntries.begin()
+                                      : this->IncludeDirectoriesEntries.end();
+
+  cmListFileBacktrace lfbt;
+  this->GetBacktrace(lfbt);
+  IncludeDirectoriesEntry entry(inc, lfbt);
+  this->IncludeDirectoriesEntries.insert(position, entry);
 
   // Property on each target:
   for (cmTargets::iterator l = this->Targets.begin();
        l != this->Targets.end(); ++l)
     {
     cmTarget &t = l->second;
-    prop = t.GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES");
-    AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before);
+    t.InsertInclude(entry, before);
     }
 }
 
@@ -3451,6 +3422,15 @@ void cmMakefile::SetProperty(const char* prop, const char* value)
     this->SetLinkDirectories(varArgsExpanded);
     return;
     }
+  if (propname == "INCLUDE_DIRECTORIES")
+    {
+    this->IncludeDirectoriesEntries.clear();
+    cmListFileBacktrace lfbt;
+    this->GetBacktrace(lfbt);
+    this->IncludeDirectoriesEntries.push_back(
+                                        IncludeDirectoriesEntry(value, lfbt));
+    return;
+    }
 
   if ( propname == "INCLUDE_REGULAR_EXPRESSION" )
     {
@@ -3482,6 +3462,14 @@ void cmMakefile::AppendProperty(const char* prop, const char* value,
   // handle special props
   std::string propname = prop;
 
+  if (propname == "INCLUDE_DIRECTORIES")
+    {
+    cmListFileBacktrace lfbt;
+    this->GetBacktrace(lfbt);
+    this->IncludeDirectoriesEntries.push_back(
+                                        IncludeDirectoriesEntry(value, lfbt));
+    return;
+    }
   if ( propname == "LINK_DIRECTORIES" )
     {
     std::vector<std::string> varArgsExpanded;
@@ -3593,6 +3581,20 @@ const char *cmMakefile::GetProperty(const char* prop,
     output = str.str();
     return output.c_str();
     }
+  else if (!strcmp("INCLUDE_DIRECTORIES",prop))
+    {
+    std::string sep;
+    for (std::vector<IncludeDirectoriesEntry>::const_iterator
+        it = this->IncludeDirectoriesEntries.begin(),
+        end = this->IncludeDirectoriesEntries.end();
+        it != end; ++it)
+      {
+      output += sep;
+      output += it->Value;
+      sep = ";";
+      }
+    return output.c_str();
+    }
 
   bool chain = false;
   const char *retVal =

+ 10 - 0
Source/cmMakefile.h

@@ -22,6 +22,7 @@
 #include "cmNewLineStyle.h"
 #include "cmGeneratorTarget.h"
 #include "cmake.h"
+#include "cmMakefileIncludeDirectoriesEntry.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmSourceGroup.h"
@@ -861,6 +862,13 @@ public:
   /** Set whether or not to report a CMP0000 violation.  */
   void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }
 
+  typedef cmMakefileIncludeDirectoriesEntry IncludeDirectoriesEntry;
+
+  std::vector<IncludeDirectoriesEntry> GetIncludeDirectoriesEntries() const
+  {
+    return this->IncludeDirectoriesEntries;
+  }
+
 protected:
   // add link libraries and directories to the target
   void AddGlobalLinkInformation(const char* name, cmTarget& target);
@@ -909,6 +917,8 @@ protected:
   std::vector<std::string> HeaderFileExtensions;
   std::string DefineFlags;
 
+  std::vector<IncludeDirectoriesEntry> IncludeDirectoriesEntries;
+
   // Track the value of the computed DEFINITIONS property.
   void AddDefineFlag(const char*, std::string&);
   void RemoveDefineFlag(const char*, std::string::size_type, std::string&);

+ 28 - 0
Source/cmMakefileIncludeDirectoriesEntry.h

@@ -0,0 +1,28 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2012 Stephen Kelly <[email protected]>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
+#ifndef cmMakefileIncludeDirectoriesEntry_h
+#define cmMakefileIncludeDirectoriesEntry_h
+
+#include <string>
+#include "cmListFileCache.h"
+
+struct cmMakefileIncludeDirectoriesEntry {
+  cmMakefileIncludeDirectoriesEntry(const std::string &value,
+                          const cmListFileBacktrace &bt)
+    : Value(value), Backtrace(bt)
+  {}
+  std::string Value;
+  cmListFileBacktrace Backtrace;
+};
+
+#endif

+ 123 - 2
Source/cmTarget.cxx

@@ -21,6 +21,7 @@
 #include "cmDocumentLocationUndefined.h"
 #include "cmListFileCache.h"
 #include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
 #include <cmsys/RegularExpression.hxx>
 #include <map>
 #include <set>
@@ -118,6 +119,14 @@ public:
   struct SourceEntry { std::vector<cmSourceFile*> Depends; };
   typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
   SourceEntriesType SourceEntries;
+
+  struct IncludeDirectoriesEntry {
+    IncludeDirectoriesEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge)
+      : ge(cge)
+    {}
+    const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
+  };
+  std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
 };
 
 //----------------------------------------------------------------------------
@@ -1392,8 +1401,14 @@ void cmTarget::SetMakefile(cmMakefile* mf)
 
   // Initialize the INCLUDE_DIRECTORIES property based on the current value
   // of the same directory property:
-  this->SetProperty("INCLUDE_DIRECTORIES",
-                    this->Makefile->GetProperty("INCLUDE_DIRECTORIES"));
+  const std::vector<cmMakefileIncludeDirectoriesEntry> parentIncludes =
+                              this->Makefile->GetIncludeDirectoriesEntries();
+
+  for (std::vector<cmMakefileIncludeDirectoriesEntry>::const_iterator it
+              = parentIncludes.begin(); it != parentIncludes.end(); ++it)
+    {
+    this->InsertInclude(*it);
+    }
 
   if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY
       || this->TargetTypeValue == cmTarget::MODULE_LIBRARY)
@@ -2445,6 +2460,20 @@ void cmTarget::GatherDependencies( const cmMakefile& mf,
     }
 }
 
+//----------------------------------------------------------------------------
+void deleteAndClear(
+      std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries)
+{
+  for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+      it = entries.begin(),
+      end = entries.end();
+      it != end; ++it)
+    {
+      delete *it;
+    }
+  entries.clear();
+}
+
 //----------------------------------------------------------------------------
 void cmTarget::SetProperty(const char* prop, const char* value)
 {
@@ -2453,6 +2482,16 @@ void cmTarget::SetProperty(const char* prop, const char* value)
     return;
     }
 
+  if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
+    {
+    cmListFileBacktrace lfbt;
+    cmGeneratorExpression ge(lfbt);
+    deleteAndClear(this->Internal->IncludeDirectoriesEntries);
+    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+    this->Internal->IncludeDirectoriesEntries.push_back(
+                          new cmTargetInternals::IncludeDirectoriesEntry(cge));
+    return;
+    }
   this->Properties.SetProperty(prop, value, cmProperty::TARGET);
   this->MaybeInvalidatePropertyCache(prop);
 }
@@ -2465,10 +2504,73 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
     {
     return;
     }
+  if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
+    {
+    cmListFileBacktrace lfbt;
+    cmGeneratorExpression ge(lfbt);
+    this->Internal->IncludeDirectoriesEntries.push_back(
+              new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value)));
+    return;
+    }
   this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString);
   this->MaybeInvalidatePropertyCache(prop);
 }
 
+//----------------------------------------------------------------------------
+void cmTarget::InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry,
+                     bool before)
+{
+  cmGeneratorExpression ge(entry.Backtrace);
+
+  std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::iterator position
+                = before ? this->Internal->IncludeDirectoriesEntries.begin()
+                         : this->Internal->IncludeDirectoriesEntries.end();
+
+  this->Internal->IncludeDirectoriesEntries.insert(position,
+      new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value)));
+}
+
+//----------------------------------------------------------------------------
+std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
+{
+  std::vector<std::string> includes;
+  std::set<std::string> uniqueIncludes;
+  cmListFileBacktrace lfbt;
+
+  cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+                                              this->GetName(),
+                                              "INCLUDE_DIRECTORIES", 0, 0);
+
+  for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+      it = this->Internal->IncludeDirectoriesEntries.begin(),
+      end = this->Internal->IncludeDirectoriesEntries.end();
+      it != end; ++it)
+    {
+    std::vector<std::string> entryIncludes;
+    cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile,
+                                              config,
+                                              false,
+                                              this,
+                                              &dagChecker),
+                                    entryIncludes);
+    for(std::vector<std::string>::const_iterator
+          li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
+      {
+      std::string inc = *li;
+      if (!cmSystemTools::IsOff(inc.c_str()))
+        {
+        cmSystemTools::ConvertToUnixSlashes(inc);
+        }
+
+      if(uniqueIncludes.insert(inc).second)
+        {
+        includes.push_back(*li);
+        }
+      }
+    }
+  return includes;
+}
+
 //----------------------------------------------------------------------------
 void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
 {
@@ -2796,6 +2898,24 @@ const char *cmTarget::GetProperty(const char* prop,
         }
       }
     }
+  if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
+    {
+    static std::string output;
+    output = "";
+    std::string sep;
+    typedef cmTargetInternals::IncludeDirectoriesEntry
+                                IncludeDirectoriesEntry;
+    for (std::vector<IncludeDirectoriesEntry*>::const_iterator
+        it = this->Internal->IncludeDirectoriesEntries.begin(),
+        end = this->Internal->IncludeDirectoriesEntries.end();
+        it != end; ++it)
+      {
+      output += sep;
+      output += (*it)->ge->GetInput();
+      sep = ";";
+      }
+    return output.c_str();
+    }
 
   if (strcmp(prop,"IMPORTED") == 0)
     {
@@ -4919,6 +5039,7 @@ cmTargetInternalPointer
 //----------------------------------------------------------------------------
 cmTargetInternalPointer::~cmTargetInternalPointer()
 {
+  deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
   delete this->Pointer;
 }
 

+ 4 - 0
Source/cmTarget.h

@@ -15,6 +15,7 @@
 #include "cmCustomCommand.h"
 #include "cmPropertyMap.h"
 #include "cmPolicies.h"
+#include "cmMakefileIncludeDirectoriesEntry.h"
 
 #include <cmsys/auto_ptr.hxx>
 
@@ -470,6 +471,9 @@ public:
   /** @return the Mac framework directory without the base. */
   std::string GetFrameworkDirectory(const char* config = 0);
 
+  std::vector<std::string> GetIncludeDirectories(const char *config);
+  void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry,
+                     bool before = false);
 private:
   /**
    * A list of direct dependencies. Use in conjunction with DependencyMap.

+ 3 - 1
Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error:
+CMake Error at BadInvalidName1.cmake:7 \(include_directories\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:Invali/dTarget,INCLUDE_DIRECTORIES>
 
   Target name not supported.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)

+ 4 - 2
Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error:
+CMake Error at BadInvalidName2.cmake:7 \(include_directories\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:Invali/dTarget,Invali/dProperty>
 
-  Target name and property name not supported.$
+  Target name and property name not supported.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)$

+ 4 - 2
Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error:
+CMake Error at BadInvalidName3.cmake:7 \(include_directories\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:Invali/dProperty>
 
-  Property name not supported.$
+  Property name not supported.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)$

+ 4 - 2
Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error:
+CMake Error at BadInvalidName4.cmake:9 \(include_directories\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:foo,Invali/dProperty>
 
-  Property name not supported.$
+  Property name not supported.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)$

+ 3 - 1
Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt

@@ -1,7 +1,9 @@
-CMake Error:
+CMake Error at BadInvalidName5.cmake:7 \(include_directories\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:,>
 
   \$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty target name and
   property name.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)$

+ 3 - 1
Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error:
+CMake Error at BadInvalidName6.cmake:7 \(include_directories\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:,ValidProperty>
 
   \$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty target name.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)$

+ 3 - 1
Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error:
+CMake Error at BadInvalidName7.cmake:9 \(include_directories\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:foo,>
 
   \$<TARGET_PROPERTY:...> expression requires a non-empty property name.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)$

+ 3 - 1
Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error:
+CMake Error at BadInvalidName8.cmake:7 \(include_directories\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:>
 
   \$<TARGET_PROPERTY:...> expression requires a non-empty property name.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)$

+ 4 - 2
Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error:
+CMake Error at BadNonTarget.cmake:7 \(include_directories\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:NonExistant,INCLUDE_DIRECTORIES>
 
-  Target "NonExistant" not found.$
+  Target "NonExistant" not found.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:8 \(include\)$