[Cmake-commits] CMake branch, next, updated. v2.8.9-838-gc99f8b0

Brad King brad.king at kitware.com
Fri Sep 28 17:11:00 EDT 2012


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  c99f8b07f8e06c4dfcd26f1b0dd242b7f368089d (commit)
       via  083de7ed35b26dceff6edeb4fc8f9d2500855a9b (commit)
       via  08cb4fa4c0378468fc2757666701617f6fe8270e (commit)
       via  0ef091d98677253c340d4045413057c50566a528 (commit)
       via  eb250cd18aaa5308eee12cf016bbfdd25a543da6 (commit)
       via  7e807472d2b17d40c702ff91c7255eca04a64ebe (commit)
       via  239ac841538be536e70cbddb2b04bef2b342a2e5 (commit)
       via  e028381bf1c5d1fdf464ed835a549be4a0569adb (commit)
      from  e98061e1c91a72997cced6957c009c50d9431d57 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c99f8b07f8e06c4dfcd26f1b0dd242b7f368089d
commit c99f8b07f8e06c4dfcd26f1b0dd242b7f368089d
Merge: e98061e 083de7e
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Sep 28 17:10:56 2012 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Fri Sep 28 17:10:56 2012 -0400

    Merge topic 'generator-expression-target-properties' into next
    
    083de7e Process generator expressions in the COMPILE_DEFINITIONS target property.
    08cb4fa Process generator expressions in the INCLUDE_DIRECTORIES property.
    0ef091d Early return if there is no target.
    eb250cd Add a self-reference check for target properties.
    7e80747 Add API to check that dependent target properties form a DAG.
    239ac84 Add a generator expression for target properties.
    e028381 Extend the generator expression language with more logic.


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=083de7ed35b26dceff6edeb4fc8f9d2500855a9b
commit 083de7ed35b26dceff6edeb4fc8f9d2500855a9b
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu Sep 20 23:28:09 2012 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Sep 28 08:50:16 2012 -0400

    Process generator expressions in the COMPILE_DEFINITIONS target property.

diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 9093613..d4b57f4 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -342,5 +342,20 @@ std::string cmGeneratorTarget::GetCompileDefinitions(const char *config)
 
   const char *prop = this->Target->GetProperty(defPropName.c_str());
 
-  return prop ? prop : "";
+  if (!prop)
+    {
+    return "";
+    }
+
+  cmListFileBacktrace lfbt;
+  cmGeneratorExpression ge(lfbt);
+
+  cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+                                             this->GetName(),
+                                             defPropName, 0, 0);
+  return ge.Parse(prop).Evaluate(this->Makefile,
+                                 config,
+                                 false,
+                                 this,
+                                 &dagChecker);
 }
diff --git a/Tests/CompileDefinitions/compiletest.cpp b/Tests/CompileDefinitions/compiletest.cpp
index 6db6f3f..4a68a07 100644
--- a/Tests/CompileDefinitions/compiletest.cpp
+++ b/Tests/CompileDefinitions/compiletest.cpp
@@ -27,6 +27,15 @@ enum {
 #endif
 };
 
+#ifdef TEST_GENERATOR_EXPRESSIONS
+#ifndef CMAKE_IS_DECLARATIVE
+#error Expect declarative definition
+#endif
+#ifdef GE_NOT_DEFINED
+#error Expect not defined generator expression
+#endif
+#endif
+
 int main(int argc, char **argv)
 {
   return 0;
diff --git a/Tests/CompileDefinitions/target_prop/CMakeLists.txt b/Tests/CompileDefinitions/target_prop/CMakeLists.txt
index e2b6ba9..fcb22b0 100644
--- a/Tests/CompileDefinitions/target_prop/CMakeLists.txt
+++ b/Tests/CompileDefinitions/target_prop/CMakeLists.txt
@@ -7,3 +7,9 @@ set_target_properties(target_prop_executable PROPERTIES COMPILE_DEFINITIONS CMAK
 
 set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun" CMAKE_IS=Fun)
 set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_FUN CMAKE_IS_="Fun")
+
+set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS
+  TEST_GENERATOR_EXPRESSIONS
+    "$<1:CMAKE_IS_DECLARATIVE>"
+    "$<0:GE_NOT_DEFINED>"
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt
new file mode 100644
index 0000000..2b22d0f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:COMPILE_DEFINITIONS>
+
+  Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake
new file mode 100644
index 0000000..74fff67
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake
@@ -0,0 +1,10 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+           "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+set_property(TARGET TargetPropertyGeneratorExpressions
+PROPERTY
+  COMPILE_DEFINITIONS "$<TARGET_PROPERTY:COMPILE_DEFINITIONS>"
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt
new file mode 100644
index 0000000..fe7caa3
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,COMPILE_DEFINITIONS>
+
+  Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake
new file mode 100644
index 0000000..d6650d3
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake
@@ -0,0 +1,10 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+           "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+set_property(TARGET TargetPropertyGeneratorExpressions PROPERTY
+COMPILE_DEFINITIONS
+  "$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,COMPILE_DEFINITIONS>"
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
index 211e6e7..f2ff05b 100644
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
@@ -4,3 +4,5 @@ run_cmake(BadSelfReference1)
 run_cmake(BadSelfReference2)
 run_cmake(BadSelfReference3)
 run_cmake(BadSelfReference4)
+run_cmake(BadSelfReference5)
+run_cmake(BadSelfReference6)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=08cb4fa4c0378468fc2757666701617f6fe8270e
commit 08cb4fa4c0378468fc2757666701617f6fe8270e
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Sep 18 13:57:07 2012 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Sep 28 08:50:10 2012 -0400

    Process generator expressions in the INCLUDE_DIRECTORIES property.
    
    This use of generator expressions, like all others to come which operate
    on target properties, must initalize the dag checker.

diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 3f58433..9093613 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -17,6 +17,8 @@
 #include "cmComputeLinkInformation.h"
 #include "cmGlobalGenerator.h"
 #include "cmSourceFile.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
 
 #include <assert.h>
 
@@ -289,11 +291,27 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories()
 {
   std::vector<std::string> includes;
   const char *prop = this->Target->GetProperty("INCLUDE_DIRECTORIES");
-  if(prop)
+  if(!prop)
     {
-    cmSystemTools::ExpandListArgument(prop, includes);
+    return includes;
     }
 
+  const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
+  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,
+                                              &dagChecker),
+                                    includes);
+
   std::set<std::string> uniqueIncludes;
   std::vector<std::string> orderedAndUniqueIncludes;
   for(std::vector<std::string>::const_iterator
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index 11c5f4e..ba81849 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -55,6 +55,11 @@ bool cmIncludeDirectoryCommand
   return true;
 }
 
+static bool StartsWithGeneratorExpression(const std::string &input)
+{
+  return input[0] == '$' && input[1] == '<';
+}
+
 // do a lot of cleanup on the arguments because this is one place where folks
 // sometimes take the output of a program and pass it directly into this
 // command not thinking that a single argument could be filled with spaces
@@ -105,7 +110,7 @@ void cmIncludeDirectoryCommand::AddDirectory(const char *i,
     cmSystemTools::ConvertToUnixSlashes(ret);
     if(!cmSystemTools::FileIsFullPath(ret.c_str()))
       {
-      if(ret[0] != '$' && ret[1] != '<')
+      if(!StartsWithGeneratorExpression(ret))
         {
         std::string tmp = this->Makefile->GetStartDirectory();
         tmp += "/";
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
index 334b8be..4b6f682 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
@@ -12,13 +12,21 @@ create_header(bar)
 create_header(bat)
 create_header(foo)
 create_header(baz)
+create_header(bang)
+create_header(bing)
+create_header(bung)
 
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
 include_directories("${CMAKE_CURRENT_BINARY_DIR}/bar")
+include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/bang>")
 
 add_executable(TargetIncludeDirectories main.cpp)
 set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/bat")
 set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foo")
+set_property(TARGET TargetIncludeDirectories APPEND PROPERTY
+    INCLUDE_DIRECTORIES "$<1:${CMAKE_CURRENT_BINARY_DIR}/bing>")
 
 include_directories("${CMAKE_CURRENT_BINARY_DIR}/baz")
+include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/bung>")
+include_directories("sing$<1:/ting>")
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
index 8aa3532..63217f4 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
@@ -3,6 +3,10 @@
 #include "bat.h"
 #include "foo.h"
 #include "baz.h"
+#include "bang.h"
+#include "bing.h"
+#include "bung.h"
+#include "ting.h"
 
 int main(int, char**)
 {
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/sing/ting/ting.h b/Tests/IncludeDirectories/TargetIncludeDirectories/sing/ting/ting.h
new file mode 100644
index 0000000..4fe01dd
--- /dev/null
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/sing/ting/ting.h
@@ -0,0 +1 @@
+//ting.h
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 3ea54f1..2fa7141 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -46,6 +46,7 @@ macro(add_RunCMake_test test)
 endmacro()
 
 add_RunCMake_test(GeneratorExpression)
+add_RunCMake_test(TargetPropertyGeneratorExpressions)
 add_RunCMake_test(Languages)
 add_RunCMake_test(ObjectLibrary)
 
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt
new file mode 100644
index 0000000..791c4a9
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
+
+  Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake
new file mode 100644
index 0000000..a85731e
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake
@@ -0,0 +1,7 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+           "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+include_directories("$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt
new file mode 100644
index 0000000..791c4a9
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
+
+  Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake
new file mode 100644
index 0000000..f1459b8
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake
@@ -0,0 +1,9 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+           "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+set_property(TARGET TargetPropertyGeneratorExpressions PROPERTY
+  INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>"
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt
new file mode 100644
index 0000000..f60d726
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>
+
+  Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake
new file mode 100644
index 0000000..433b730
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake
@@ -0,0 +1,8 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+           "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+include_directories(
+  "$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt
new file mode 100644
index 0000000..f60d726
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>
+
+  Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake
new file mode 100644
index 0000000..4b64459
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake
@@ -0,0 +1,10 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+           "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+set_property(TARGET TargetPropertyGeneratorExpressions PROPERTY
+INCLUDE_DIRECTORIES
+  "$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>"
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt
new file mode 100644
index 0000000..22577da
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt
@@ -0,0 +1,8 @@
+
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} CXX)
+
+# MSVC creates extra targets which pollute the stderr unless we set this.
+set(CMAKE_SUPPRESS_REGENERATION TRUE)
+
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
new file mode 100644
index 0000000..211e6e7
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
@@ -0,0 +1,6 @@
+include(RunCMake)
+
+run_cmake(BadSelfReference1)
+run_cmake(BadSelfReference2)
+run_cmake(BadSelfReference3)
+run_cmake(BadSelfReference4)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0ef091d98677253c340d4045413057c50566a528
commit 0ef091d98677253c340d4045413057c50566a528
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Aug 19 23:14:15 2012 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Sep 28 08:49:21 2012 -0400

    Early return if there is no target.
    
    The remainder of this method depends on the target existing (otherwise
    the includes container would be empty), so make the code a little more
    readable.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 62b6ce7..3f6fe03 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1390,6 +1390,11 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
       }
     }
 
+  if(!target)
+    {
+    return;
+    }
+
   // Load implicit include directories for this language.
   std::string impDirVar = "CMAKE_";
   impDirVar += lang;
@@ -1407,10 +1412,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
 
   // Get the target-specific include directories.
   std::vector<std::string> includes;
-  if(target)
-    {
-    includes = target->GetIncludeDirectories();
-    }
+
+  includes = target->GetIncludeDirectories();
 
   // Support putting all the in-project include directories first if
   // it is requested by the project.

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=eb250cd18aaa5308eee12cf016bbfdd25a543da6
commit eb250cd18aaa5308eee12cf016bbfdd25a543da6
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Sep 18 13:53:39 2012 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Sep 28 08:49:21 2012 -0400

    Add a self-reference check for target properties.
    
    Prevent constructs like:
    
     ... INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>"
    
    Indirect self-references (cycles) are also prevented here, but
    indirect generator expression references of any kind are not
    possible yet anyway.

diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index a9e28c3..67bcc0b 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -14,6 +14,7 @@
 #include "cmGeneratorExpressionEvaluator.h"
 #include "cmGeneratorExpressionParser.h"
 #include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorExpression.h"
 
 //----------------------------------------------------------------------------
 static void reportError(cmGeneratorExpressionContext *context,
@@ -264,7 +265,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
   std::string Evaluate(const std::vector<std::string> &parameters,
                        cmGeneratorExpressionContext *context,
                        const GeneratorExpressionContent *content,
-                       cmGeneratorExpressionDAGChecker *) const
+                       cmGeneratorExpressionDAGChecker *dagCheckerParent
+                      ) const
   {
     if (parameters.size() != 1 && parameters.size() != 2)
       {
@@ -289,6 +291,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
         }
       propertyName = parameters.at(1);
       }
+
+    cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
+                                               target->GetName(),
+                                               propertyName,
+                                               content,
+                                               dagCheckerParent);
+
+    if (!dagChecker.check())
+      {
+      dagChecker.reportError(context, content->GetOriginalExpression());
+      return std::string();
+      }
+
     const char *prop = target->GetProperty(propertyName.c_str());
     return prop ? prop : "";
   }

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7e807472d2b17d40c702ff91c7255eca04a64ebe
commit 7e807472d2b17d40c702ff91c7255eca04a64ebe
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Sep 18 13:42:23 2012 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Sep 28 08:49:21 2012 -0400

    Add API to check that dependent target properties form a DAG.
    
    Initially this will only be used to check for self-references, but
    can be extended to check for cycles when chaining properties of other
    targets.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 354f123..5a3e7d1 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -183,6 +183,8 @@ set(SRCS
   cmFileTimeComparison.cxx
   cmFileTimeComparison.h
   cmGeneratedFileStream.cxx
+  cmGeneratorExpressionDAGChecker.cxx
+  cmGeneratorExpressionDAGChecker.h
   cmGeneratorExpressionEvaluator.cxx
   cmGeneratorExpressionEvaluator.h
   cmGeneratorExpressionLexer.cxx
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 55a1e3e..3f8e962 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -19,6 +19,7 @@
 #include "cmGeneratorExpressionEvaluator.h"
 #include "cmGeneratorExpressionLexer.h"
 #include "cmGeneratorExpressionParser.h"
+#include "cmGeneratorExpressionDAGChecker.h"
 
 //----------------------------------------------------------------------------
 cmGeneratorExpression::cmGeneratorExpression(
@@ -66,7 +67,8 @@ cmGeneratorExpression::~cmGeneratorExpression()
 //----------------------------------------------------------------------------
 const char *cmCompiledGeneratorExpression::Evaluate(
   cmMakefile* mf, const char* config, bool quiet,
-  cmGeneratorTarget *target) const
+  cmGeneratorTarget *target,
+  cmGeneratorExpressionDAGChecker *dagChecker) const
 {
   if (!this->NeedsParsing)
     {
@@ -90,7 +92,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
 
   for ( ; it != end; ++it)
     {
-    this->Output += (*it)->Evaluate(&context);
+    this->Output += (*it)->Evaluate(&context, dagChecker);
     if (context.HadError)
       {
       this->Output = "";
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index fdf45a1..d37ce97 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -25,6 +25,7 @@ class cmMakefile;
 class cmListFileBacktrace;
 
 struct cmGeneratorExpressionEvaluator;
+struct cmGeneratorExpressionDAGChecker;
 
 class cmCompiledGeneratorExpression;
 
@@ -60,7 +61,8 @@ class cmCompiledGeneratorExpression
 public:
   const char* Evaluate(cmMakefile* mf, const char* config,
                        bool quiet = false,
-                       cmGeneratorTarget *target = 0) const;
+                       cmGeneratorTarget *target = 0,
+                       cmGeneratorExpressionDAGChecker *dagChecker = 0) const;
 
   /** Get set of targets found during evaluations.  */
   std::set<cmTarget*> const& GetTargets() const
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
new file mode 100644
index 0000000..bfb0ddf
--- /dev/null
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -0,0 +1,106 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2012 Stephen Kelly <steveire at gmail.com>
+
+  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.
+============================================================================*/
+
+#include "cmGeneratorExpressionDAGChecker.h"
+
+#include "cmMakefile.h"
+
+//----------------------------------------------------------------------------
+cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
+                const cmListFileBacktrace &backtrace,
+                const std::string &target,
+                const std::string &property,
+                const GeneratorExpressionContent *content,
+                cmGeneratorExpressionDAGChecker *parent)
+  : Parent(parent), Target(target), Property(property),
+    Content(content), Backtrace(backtrace)
+{
+  this->IsDAG = this->isDAG();
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::check() const
+{
+  return this->IsDAG;
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorExpressionDAGChecker::reportError(
+                  cmGeneratorExpressionContext *context,
+                  const std::string &expr)
+{
+  if (this->IsDAG)
+    {
+    return;
+    }
+
+  context->HadError = true;
+  if (context->Quiet)
+    {
+    return;
+    }
+
+  const cmGeneratorExpressionDAGChecker *parent = this->Parent;
+
+  if (parent && !parent->Parent)
+    {
+    cmOStringStream e;
+    e << "Error evaluating generator expression:\n"
+      << "  " << expr << "\n"
+      << "Self reference on target \""
+      << context->Target->GetName() << "\".\n";
+    context->Makefile->GetCMakeInstance()
+      ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
+                      parent->Backtrace);
+    return;
+    }
+
+  {
+  cmOStringStream e;
+  e << "Error evaluating generator expression:\n"
+    << "  " << expr << "\n"
+    << "Dependency loop found.";
+  context->Makefile->GetCMakeInstance()
+    ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
+                    context->Backtrace);
+  }
+
+  int loopStep = 1;
+  while (parent)
+    {
+    cmOStringStream e;
+    e << "Loop step " << loopStep << "\n"
+      << "  "
+      << (parent->Content ? parent->Content->GetOriginalExpression() : expr)
+      << "\n";
+    context->Makefile->GetCMakeInstance()
+      ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
+                      parent->Backtrace);
+    parent = parent->Parent;
+    ++loopStep;
+    }
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::isDAG() const
+{
+  const cmGeneratorExpressionDAGChecker *parent = this->Parent;
+  while (parent)
+    {
+    if (this->Target == parent->Target && this->Property == parent->Property)
+      {
+      return false;
+      }
+    parent = parent->Parent;
+    }
+  return true;
+}
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
new file mode 100644
index 0000000..ffc84f8
--- /dev/null
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -0,0 +1,44 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2012 Stephen Kelly <steveire at gmail.com>
+
+  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 cmGeneratorExpressionDAGChecker_h
+#define cmGeneratorExpressionDAGChecker_h
+
+#include "cmStandardIncludes.h"
+
+#include "cmGeneratorExpressionEvaluator.h"
+
+//----------------------------------------------------------------------------
+struct cmGeneratorExpressionDAGChecker
+{
+  cmGeneratorExpressionDAGChecker(const cmListFileBacktrace &backtrace,
+                                  const std::string &target,
+                                  const std::string &property,
+                                  const GeneratorExpressionContent *content,
+                                  cmGeneratorExpressionDAGChecker *parent);
+
+  bool check() const;
+
+  void reportError(cmGeneratorExpressionContext *context,
+                   const std::string &expr);
+private:
+  bool isDAG() const;
+
+private:
+  const cmGeneratorExpressionDAGChecker * const Parent;
+  const std::string Target;
+  const std::string Property;
+  const GeneratorExpressionContent * const Content;
+  const cmListFileBacktrace Backtrace;
+  bool IsDAG;
+};
+
+#endif
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 1583270..a9e28c3 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -13,6 +13,7 @@
 
 #include "cmGeneratorExpressionEvaluator.h"
 #include "cmGeneratorExpressionParser.h"
+#include "cmGeneratorExpressionDAGChecker.h"
 
 //----------------------------------------------------------------------------
 static void reportError(cmGeneratorExpressionContext *context,
@@ -47,7 +48,8 @@ struct cmGeneratorExpressionNode
 
   virtual std::string Evaluate(const std::vector<std::string> &parameters,
                                cmGeneratorExpressionContext *context,
-                               const GeneratorExpressionContent *content
+                               const GeneratorExpressionContent *content,
+                               cmGeneratorExpressionDAGChecker *dagChecker
                               ) const = 0;
 };
 
@@ -60,7 +62,8 @@ static const struct ZeroNode : public cmGeneratorExpressionNode
 
   std::string Evaluate(const std::vector<std::string> &,
                        cmGeneratorExpressionContext *,
-                       const GeneratorExpressionContent *) const
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     // Unreachable
     return std::string();
@@ -76,7 +79,8 @@ static const struct OneNode : public cmGeneratorExpressionNode
 
   std::string Evaluate(const std::vector<std::string> &,
                        cmGeneratorExpressionContext *,
-                       const GeneratorExpressionContent *) const
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     // Unreachable
     return std::string();
@@ -93,7 +97,8 @@ static const struct OP ## Node : public cmGeneratorExpressionNode \
  \
   std::string Evaluate(const std::vector<std::string> &parameters, \
                        cmGeneratorExpressionContext *context, \
-                       const GeneratorExpressionContent *content) const \
+                       const GeneratorExpressionContent *content, \
+                       cmGeneratorExpressionDAGChecker *) const \
   { \
     std::vector<std::string>::const_iterator it = parameters.begin(); \
     const std::vector<std::string>::const_iterator end = parameters.end(); \
@@ -123,9 +128,11 @@ BOOLEAN_OP_NODE(orNode, OR, 0, 1)
 static const struct NotNode : public cmGeneratorExpressionNode
 {
   NotNode() {}
+
   std::string Evaluate(const std::vector<std::string> &parameters,
                        cmGeneratorExpressionContext *context,
-                       const GeneratorExpressionContent *content) const
+                       const GeneratorExpressionContent *content,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     if (*parameters.begin() != "0" && *parameters.begin() != "1")
       {
@@ -146,7 +153,8 @@ static const struct BoolNode : public cmGeneratorExpressionNode
 
   std::string Evaluate(const std::vector<std::string> &parameters,
                        cmGeneratorExpressionContext *,
-                       const GeneratorExpressionContent *) const
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
   }
@@ -161,7 +169,8 @@ static const struct StrEqualNode : public cmGeneratorExpressionNode
 
   std::string Evaluate(const std::vector<std::string> &parameters,
                        cmGeneratorExpressionContext *,
-                       const GeneratorExpressionContent *) const
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     return *parameters.begin() == parameters.at(1) ? "1" : "0";
   }
@@ -176,7 +185,8 @@ static const struct Angle_RNode : public cmGeneratorExpressionNode
 
   std::string Evaluate(const std::vector<std::string> &,
                        cmGeneratorExpressionContext *,
-                       const GeneratorExpressionContent *) const
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     return ">";
   }
@@ -191,7 +201,8 @@ static const struct CommaNode : public cmGeneratorExpressionNode
 
   std::string Evaluate(const std::vector<std::string> &,
                        cmGeneratorExpressionContext *,
-                       const GeneratorExpressionContent *) const
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     return ",";
   }
@@ -201,11 +212,13 @@ static const struct CommaNode : public cmGeneratorExpressionNode
 static const struct ConfigurationNode : public cmGeneratorExpressionNode
 {
   ConfigurationNode() {}
+
   virtual int NumExpectedParameters() const { return 0; }
 
   std::string Evaluate(const std::vector<std::string> &,
                        cmGeneratorExpressionContext *context,
-                       const GeneratorExpressionContent *) const
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     return context->Config ? context->Config : "";
   }
@@ -220,7 +233,8 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
 
   std::string Evaluate(const std::vector<std::string> &parameters,
                        cmGeneratorExpressionContext *context,
-                       const GeneratorExpressionContent *content) const
+                       const GeneratorExpressionContent *content,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     if (!context->Config)
       {
@@ -240,7 +254,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
 } configurationTestNode;
 
 //----------------------------------------------------------------------------
-static const struct TargetPropertyNode: public cmGeneratorExpressionNode
+static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 {
   TargetPropertyNode() {}
 
@@ -249,7 +263,8 @@ static const struct TargetPropertyNode: public cmGeneratorExpressionNode
 
   std::string Evaluate(const std::vector<std::string> &parameters,
                        cmGeneratorExpressionContext *context,
-                       const GeneratorExpressionContent *content) const
+                       const GeneratorExpressionContent *content,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     if (parameters.size() != 1 && parameters.size() != 2)
       {
@@ -393,7 +408,8 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
 
   std::string Evaluate(const std::vector<std::string> &parameters,
                        cmGeneratorExpressionContext *context,
-                       const GeneratorExpressionContent *content) const
+                       const GeneratorExpressionContent *content,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     // Lookup the referenced target.
     std::string name = *parameters.begin();
@@ -523,7 +539,8 @@ std::string GeneratorExpressionContent::GetOriginalExpression() const
 
 //----------------------------------------------------------------------------
 std::string GeneratorExpressionContent::Evaluate(
-                                  cmGeneratorExpressionContext *context) const
+                            cmGeneratorExpressionContext *context,
+                            cmGeneratorExpressionDAGChecker *dagChecker) const
 {
   std::string identifier;
   {
@@ -533,7 +550,7 @@ std::string GeneratorExpressionContent::Evaluate(
                                           = this->IdentifierChildren.end();
   for ( ; it != end; ++it)
     {
-    identifier += (*it)->Evaluate(context);
+    identifier += (*it)->Evaluate(context, dagChecker);
     if (context->HadError)
       {
       return std::string();
@@ -576,7 +593,7 @@ std::string GeneratorExpressionContent::Evaluate(
                                                                 = pit->end();
       for ( ; it != end; ++it)
         {
-        result += (*it)->Evaluate(context);
+        result += (*it)->Evaluate(context, dagChecker);
         if (context->HadError)
           {
           return std::string();
@@ -602,7 +619,7 @@ std::string GeneratorExpressionContent::Evaluate(
                                                               pit->end();
     for ( ; it != end; ++it)
       {
-      parameter += (*it)->Evaluate(context);
+      parameter += (*it)->Evaluate(context, dagChecker);
       if (context->HadError)
         {
         return std::string();
@@ -645,7 +662,7 @@ std::string GeneratorExpressionContent::Evaluate(
     return std::string();
     }
 
-  return node->Evaluate(parameters, context, this);
+  return node->Evaluate(parameters, context, this, dagChecker);
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 4086e8e..04a2acd 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -32,6 +32,8 @@ struct cmGeneratorExpressionContext
   bool HadError;
 };
 
+struct cmGeneratorExpressionDAGChecker;
+
 //----------------------------------------------------------------------------
 struct cmGeneratorExpressionEvaluator
 {
@@ -46,8 +48,8 @@ struct cmGeneratorExpressionEvaluator
 
   virtual Type GetType() const = 0;
 
-  virtual std::string Evaluate(cmGeneratorExpressionContext *context
-                              ) const = 0;
+  virtual std::string Evaluate(cmGeneratorExpressionContext *context,
+                              cmGeneratorExpressionDAGChecker *) const = 0;
 
 private:
   cmGeneratorExpressionEvaluator(const cmGeneratorExpressionEvaluator &);
@@ -62,7 +64,8 @@ struct TextContent : public cmGeneratorExpressionEvaluator
 
   }
 
-  std::string Evaluate(cmGeneratorExpressionContext *) const
+  std::string Evaluate(cmGeneratorExpressionContext *,
+                       cmGeneratorExpressionDAGChecker *) const
   {
     return std::string(this->Content, this->Length);
   }
@@ -107,7 +110,8 @@ struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
     return cmGeneratorExpressionEvaluator::Generator;
   }
 
-  std::string Evaluate(cmGeneratorExpressionContext *context) const;
+  std::string Evaluate(cmGeneratorExpressionContext *context,
+                       cmGeneratorExpressionDAGChecker *) const;
 
   std::string GetOriginalExpression() const;
 
diff --git a/bootstrap b/bootstrap
index 23134d0..89c9012 100755
--- a/bootstrap
+++ b/bootstrap
@@ -202,6 +202,7 @@ CMAKE_CXX_SOURCES="\
   cmInstallDirectoryGenerator \
   cmGeneratedFileStream \
   cmGeneratorTarget \
+  cmGeneratorExpressionDAGChecker \
   cmGeneratorExpressionEvaluator \
   cmGeneratorExpressionLexer \
   cmGeneratorExpressionParser \

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=239ac841538be536e70cbddb2b04bef2b342a2e5
commit 239ac841538be536e70cbddb2b04bef2b342a2e5
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Wed Sep 12 04:23:31 2012 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Sep 28 08:49:21 2012 -0400

    Add a generator expression for target properties.
    
    There are two overloads, so that it can use the operational
    target when a target property is being evaluated, and a target
    can alternatively be specified by name.
    
    At this point, the generators don't chain. That comes later.

diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h
index b11bff9..6a0cd9d 100644
--- a/Source/cmAddTestCommand.h
+++ b/Source/cmAddTestCommand.h
@@ -81,7 +81,7 @@ public:
       "\n"
       "Arguments after COMMAND may use \"generator expressions\" with the "
       "syntax \"$<...>\".  "
-      CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+      CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS
       "Example usage:\n"
       "  add_test(NAME mytest\n"
       "           COMMAND testDriver --config $<CONFIGURATION>\n"
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 5622da0..6b0cf49 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -12,7 +12,7 @@
 #ifndef cmDocumentGeneratorExpressions_h
 #define cmDocumentGeneratorExpressions_h
 
-#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS                       \
+#define CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS                      \
   "Generator expressions are evaluted during build system generation "  \
   "to produce information specific to each build configuration.  "      \
   "Valid expressions are:\n"                                            \
@@ -35,11 +35,20 @@
   "  $<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>\n"                  \
   "  $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n"    \
   "  $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n"    \
+  "  $<TARGET_PROPERTY:tgt,prop>   = The value of the property prop\n"  \
+  "the target tgt. Note that tgt is not added as a dependency of the "  \
+  "target this expression is evaluated on.\n" \
   "Boolean expressions:\n"                                              \
   "  $<AND:?[,?]...>           = '1' if all '?' are '1', else '0'\n"    \
   "  $<OR:?[,?]...>            = '0' if all '?' are '0', else '1'\n"    \
   "  $<NOT:?>                  = '0' if '?' is '1', else '1'\n"         \
   "where '?' is always either '0' or '1'.\n"                            \
+
+#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS                       \
+  CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
+  "Expressions with an implicit 'this' target:"                         \
+  "  $<TARGET_PROPERTY:prop>   = The value of the property prop on\n"   \
+  "the target on which the generator expression is evaluated.\n"        \
   ""
 
 #endif
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 0885616..55a1e3e 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -65,7 +65,8 @@ cmGeneratorExpression::~cmGeneratorExpression()
 
 //----------------------------------------------------------------------------
 const char *cmCompiledGeneratorExpression::Evaluate(
-  cmMakefile* mf, const char* config, bool quiet) const
+  cmMakefile* mf, const char* config, bool quiet,
+  cmGeneratorTarget *target) const
 {
   if (!this->NeedsParsing)
     {
@@ -84,6 +85,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
   context.Config = config;
   context.Quiet = quiet;
   context.HadError = false;
+  context.Target = target;
   context.Backtrace = this->Backtrace;
 
   for ( ; it != end; ++it)
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 780ccfc..fdf45a1 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -20,6 +20,7 @@
 #include <cmsys/RegularExpression.hxx>
 
 class cmTarget;
+class cmGeneratorTarget;
 class cmMakefile;
 class cmListFileBacktrace;
 
@@ -58,7 +59,8 @@ class cmCompiledGeneratorExpression
 {
 public:
   const char* Evaluate(cmMakefile* mf, const char* config,
-                        bool quiet = false) const;
+                       bool quiet = false,
+                       cmGeneratorTarget *target = 0) const;
 
   /** Get set of targets found during evaluations.  */
   std::set<cmTarget*> const& GetTargets() const
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 8573273..1583270 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -240,6 +240,46 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
 } configurationTestNode;
 
 //----------------------------------------------------------------------------
+static const struct TargetPropertyNode: public cmGeneratorExpressionNode
+{
+  TargetPropertyNode() {}
+
+  // This node handles errors on parameter count itself.
+  virtual int NumExpectedParameters() const { return -1; }
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *context,
+                       const GeneratorExpressionContent *content) const
+  {
+    if (parameters.size() != 1 && parameters.size() != 2)
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<TARGET_PROPERTY:...> expression requires one or two parameters");
+      return std::string();
+      }
+    cmGeneratorTarget* target = context->Target;
+    std::string propertyName = *parameters.begin();
+    if (parameters.size() == 2)
+      {
+      target = context->Makefile->FindGeneratorTargetToUse(
+                                                parameters.begin()->c_str());
+
+      if (!target)
+        {
+        cmOStringStream e;
+        e << "Target \""
+          << target
+          << "\" not found.";
+        reportError(context, content->GetOriginalExpression(), e.str());
+        }
+      propertyName = parameters.at(1);
+      }
+    const char *prop = target->GetProperty(propertyName.c_str());
+    return prop ? prop : "";
+  }
+} targetPropertyNode;
+
+//----------------------------------------------------------------------------
 template<bool linker, bool soname>
 struct TargetFilesystemArtifactResultCreator
 {
@@ -460,7 +500,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     return &angle_rNode;
   else if (identifier == "COMMA")
     return &commaNode;
+  else if (identifier == "TARGET_PROPERTY")
+    return &targetPropertyNode;
   return 0;
+
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 5163ca0..4086e8e 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -15,6 +15,11 @@
 #include <vector>
 #include <string>
 
+#include "cmListFileCache.h"
+
+class cmTarget;
+class cmGeneratorTarget;
+
 //----------------------------------------------------------------------------
 struct cmGeneratorExpressionContext
 {
@@ -22,7 +27,7 @@ struct cmGeneratorExpressionContext
   std::set<cmTarget*> Targets;
   cmMakefile *Makefile;
   const char *Config;
-  cmTarget *Target;
+  cmGeneratorTarget *Target;
   bool Quiet;
   bool HadError;
 };

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e028381bf1c5d1fdf464ed835a549be4a0569adb
commit e028381bf1c5d1fdf464ed835a549be4a0569adb
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Wed Sep 12 04:20:42 2012 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Sep 28 08:49:21 2012 -0400

    Extend the generator expression language with more logic.
    
    Generator expressions for comparing strings, evaluating
    strings as booleans, and for creating literal right-angle-brackets
    and commas are added. Those may be needed in some cases
    where they appear in literals.

diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 74c673a..5622da0 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -20,6 +20,12 @@
   "  $<1:...>                  = content of \"...\"\n"                  \
   "  $<CONFIG:cfg>             = '1' if config is \"cfg\", else '0'\n"  \
   "  $<CONFIGURATION>          = configuration name\n"                  \
+  "  $<BOOL:...>               = '1' if the '...' is true, else '0'\n"  \
+  "  $<STREQUAL:a,b>           = '1' if a is STREQUAL b, else '0'\n"    \
+  "  $<ANGLE-R>                = A literal '>'. Used to compare "       \
+  "strings which contain a '>' for example.\n"                          \
+  "  $<COMMA>                  = A literal ','. Used to compare "       \
+  "strings which contain a ',' for example.\n"                          \
   "  $<TARGET_FILE:tgt>        = main file (.exe, .so.1.2, .a)\n"       \
   "  $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n"   \
   "  $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n"            \
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index acc844a..8573273 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -138,6 +138,66 @@ static const struct NotNode : public cmGeneratorExpressionNode
 } notNode;
 
 //----------------------------------------------------------------------------
+static const struct BoolNode : public cmGeneratorExpressionNode
+{
+  BoolNode() {}
+
+  virtual int NumExpectedParameters() const { return 1; }
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *,
+                       const GeneratorExpressionContent *) const
+  {
+    return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
+  }
+} boolNode;
+
+//----------------------------------------------------------------------------
+static const struct StrEqualNode : public cmGeneratorExpressionNode
+{
+  StrEqualNode() {}
+
+  virtual int NumExpectedParameters() const { return 2; }
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *,
+                       const GeneratorExpressionContent *) const
+  {
+    return *parameters.begin() == parameters.at(1) ? "1" : "0";
+  }
+} strEqualNode;
+
+//----------------------------------------------------------------------------
+static const struct Angle_RNode : public cmGeneratorExpressionNode
+{
+  Angle_RNode() {}
+
+  virtual int NumExpectedParameters() const { return 0; }
+
+  std::string Evaluate(const std::vector<std::string> &,
+                       cmGeneratorExpressionContext *,
+                       const GeneratorExpressionContent *) const
+  {
+    return ">";
+  }
+} angle_rNode;
+
+//----------------------------------------------------------------------------
+static const struct CommaNode : public cmGeneratorExpressionNode
+{
+  CommaNode() {}
+
+  virtual int NumExpectedParameters() const { return 0; }
+
+  std::string Evaluate(const std::vector<std::string> &,
+                       cmGeneratorExpressionContext *,
+                       const GeneratorExpressionContent *) const
+  {
+    return ",";
+  }
+} commaNode;
+
+//----------------------------------------------------------------------------
 static const struct ConfigurationNode : public cmGeneratorExpressionNode
 {
   ConfigurationNode() {}
@@ -392,6 +452,14 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     return &targetLinkerFileDirNode;
   else if (identifier == "TARGET_SONAME_FILE_DIR")
     return &targetSoNameFileDirNode;
+  else if (identifier == "STREQUAL")
+    return &strEqualNode;
+  else if (identifier == "BOOL")
+    return &boolNode;
+  else if (identifier == "ANGLE-R")
+    return &angle_rNode;
+  else if (identifier == "COMMA")
+    return &commaNode;
   return 0;
 }
 
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index 2b135dc..79a8abb 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -22,6 +22,23 @@ add_custom_target(check ALL
     -Dtest_or_1=$<OR:1>
     -Dtest_or_1_0=$<OR:1,0>
     -Dtest_or_1_1=$<OR:1,1>
+    -Dtest_bool_notfound=$<BOOL:NOTFOUND>
+    -Dtest_bool_foo_notfound=$<BOOL:Foo-NOTFOUND>
+    -Dtest_bool_true=$<BOOL:True>
+    -Dtest_bool_false=$<BOOL:False>
+    -Dtest_bool_on=$<BOOL:On>
+    -Dtest_bool_off=$<BOOL:Off>
+    -Dtest_bool_no=$<BOOL:No>
+    -Dtest_bool_n=$<BOOL:N>
+    -Dtest_strequal_yes_yes=$<STREQUAL:Yes,Yes>
+    -Dtest_strequal_yes_yes_cs=$<STREQUAL:Yes,yes>
+    -Dtest_strequal_yes_no=$<STREQUAL:Yes,No>
+    -Dtest_strequal_no_yes=$<STREQUAL:No,Yes>
+    -Dtest_strequal_angle_r=$<STREQUAL:$<ANGLE-R>,$<ANGLE-R>>
+    -Dtest_strequal_comma=$<STREQUAL:$<COMMA>,$<COMMA>>
+    -Dtest_strequal_angle_r_comma=$<STREQUAL:$<ANGLE-R>,$<COMMA>>
+    -Dtest_angle_r=$<ANGLE-R>
+    -Dtest_comma=$<COMMA>
     -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
   COMMAND ${CMAKE_COMMAND} -E echo "check done"
   VERBATIM
diff --git a/Tests/GeneratorExpression/check.cmake b/Tests/GeneratorExpression/check.cmake
index e243d85..6fb87a2 100644
--- a/Tests/GeneratorExpression/check.cmake
+++ b/Tests/GeneratorExpression/check.cmake
@@ -23,3 +23,20 @@ check(test_or_0_1 "1")
 check(test_or_1 "1")
 check(test_or_1_0 "1")
 check(test_or_1_1 "1")
+check(test_bool_notfound "0")
+check(test_bool_foo_notfound "0")
+check(test_bool_true "1")
+check(test_bool_false "0")
+check(test_bool_on "1")
+check(test_bool_off "0")
+check(test_bool_no "0")
+check(test_bool_n "0")
+check(test_strequal_yes_yes "1")
+check(test_strequal_yes_yes_cs "0")
+check(test_strequal_yes_no "0")
+check(test_strequal_no_yes "0")
+check(test_strequal_angle_r "1")
+check(test_strequal_comma "1")
+check(test_strequal_angle_r_comma "0")
+check(test_angle_r ">")
+check(test_comma ",")

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list