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  c26a74cf300772f1e4eaeb0228531b23e3a5e228 (commit)
       via  894f52f32d96ae92df0ba3dac2a70fe9c87e818d (commit)
       via  f5b1980fb27fa902d37856ec3e22daddfeb9d52f (commit)
       via  c67b8124f735e7f96567a276e16969607b300e43 (commit)
       via  d0f950fdba88ac08d0e25e340fe558eba008810e (commit)
       via  26def1771dfbf502129212c9e728e34860477fac (commit)
       via  0c657dc637ca4da6861102c7306069ad157ec08d (commit)
       via  e04f737c7a3e66c49e2d50813af1fa40a415eff8 (commit)
      from  6d2c1fc986d802559d56e238bf444d65769214a5 (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=c26a74cf300772f1e4eaeb0228531b23e3a5e228
commit c26a74cf300772f1e4eaeb0228531b23e3a5e228
Merge: 6d2c1fc 894f52f
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Fri Jan 4 19:20:45 2013 -0500
Commit:     CMake Topic Stage <kwro...@kitware.com>
CommitDate: Fri Jan 4 19:20:45 2013 -0500

    Merge topic 'interface-includes-defines' into next
    
    894f52f Handle INTERFACE properties transitively for includes and defines.
    f5b1980 Populate the ExportedTargets member early in GenerateMainFile
    c67b812 Make cycles in target properties ignored, not an error.
    d0f950f Use mapped config properties to evaluate $<CONFIG>
    26def17 Make all relevant targets available in the genex context.
    0c657dc Add API to populate INTERFACE properties in exported targets.
    e04f737 Add API to extract target names from a genex string.


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=894f52f32d96ae92df0ba3dac2a70fe9c87e818d
commit 894f52f32d96ae92df0ba3dac2a70fe9c87e818d
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Sep 23 13:45:17 2012 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Jan 5 01:18:37 2013 +0100

    Handle INTERFACE properties transitively for includes and defines.
    
    Contextually, the behavior is as if the properties content from another
    target is included in the string and then the result is evaluated.

diff --git a/Source/cmExportBuildFileGenerator.cxx 
b/Source/cmExportBuildFileGenerator.cxx
index 3e9a9fd..9533319 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -52,6 +52,8 @@ bool 
cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
   this->GenerateExpectedTargetsCode(os, expectedTargets);
   }
 
+  std::vector<std::string> missingTargets;
+
   // Create all the imported targets.
   for(std::vector<cmTarget*>::const_iterator
         tei = allTargets.begin();
@@ -59,8 +61,21 @@ bool 
cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
     {
     cmTarget* te = *tei;
     this->GenerateImportTargetCode(os, te);
+
+    ImportPropertyMap properties;
+
+    this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te,
+                                    cmGeneratorExpression::BuildInterface,
+                                    properties, missingTargets);
+    this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te,
+                                    cmGeneratorExpression::BuildInterface,
+                                    properties, missingTargets);
+
+    this->GenerateInterfaceProperties(te, os, properties);
     }
 
+  this->GenerateMissingTargetsCheckCode(os, missingTargets);
+
   // Generate import file content for each configuration.
   for(std::vector<std::string>::const_iterator
         ci = this->Configurations.begin();
diff --git a/Source/cmExportInstallFileGenerator.cxx 
b/Source/cmExportInstallFileGenerator.cxx
index 2b7937e..bc953c9 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -69,6 +69,8 @@ bool 
cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
   this->GenerateExpectedTargetsCode(os, expectedTargets);
   }
 
+  std::vector<std::string> missingTargets;
+
   // Create all the imported targets.
   for(std::vector<cmTarget*>::const_iterator
         tei = allTargets.begin();
@@ -76,8 +78,23 @@ bool 
cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
     {
     cmTarget* te = *tei;
     this->GenerateImportTargetCode(os, te);
+
+    ImportPropertyMap properties;
+
+    this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES",
+                                  te,
+                                  cmGeneratorExpression::InstallInterface,
+                                  properties, missingTargets);
+    this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS",
+                                  te,
+                                  cmGeneratorExpression::InstallInterface,
+                                  properties, missingTargets);
+
+    this->GenerateInterfaceProperties(te, os, properties);
     }
 
+  this->GenerateMissingTargetsCheckCode(os, missingTargets);
+
   // Now load per-configuration properties for them.
   os << "# Load information for each installed configuration.\n"
      << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx 
b/Source/cmGeneratorExpressionEvaluator.cxx
index 4b44ebe..b7ce155 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -286,6 +286,13 @@ static const struct ConfigurationTestNode : public 
cmGeneratorExpressionNode
   }
 } configurationTestNode;
 
+
+//----------------------------------------------------------------------------
+static const char* targetPropertyTransitiveWhitelist[] = {
+    "INTERFACE_INCLUDE_DIRECTORIES"
+  , "INTERFACE_COMPILE_DEFINITIONS"
+};
+
 //----------------------------------------------------------------------------
 static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 {
@@ -394,7 +401,28 @@ static const struct TargetPropertyNode : public 
cmGeneratorExpressionNode
       }
 
     const char *prop = target->GetProperty(propertyName.c_str());
-    return prop ? prop : "";
+    if (!prop)
+      {
+      return std::string();
+      }
+
+    for (size_t i = 0;
+         i < (sizeof(targetPropertyTransitiveWhitelist) /
+              sizeof(*targetPropertyTransitiveWhitelist));
+         ++i)
+      {
+      if (targetPropertyTransitiveWhitelist[i] == propertyName)
+        {
+        cmGeneratorExpression ge(context->Backtrace);
+        return ge.Parse(prop)->Evaluate(context->Makefile,
+                            context->Config,
+                            context->Quiet,
+                            context->HeadTarget,
+                            target,
+                            &dagChecker);
+        }
+      }
+    return prop;
   }
 } targetPropertyNode;
 
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index d60979c..ca53a39 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -720,6 +720,28 @@ void cmTarget::DefineProperties(cmake *cm)
      "for the named configuration.");
 
   cm->DefineProperty
+    ("INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET,
+     "List of public include directories for a library.",
+     "Targets may populate this property to publish the include directories "
+     "required to compile against the headers for the target.  Consuming "
+     "targets can add entries to their own INCLUDE_DIRECTORIES property such "
+     "as $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> to use the "
+     "include directories specified in the interface of 'foo'."
+     "\n"
+     CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+
+  cm->DefineProperty
+    ("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET,
+     "List of public compile definitions for a library.",
+     "Targets may populate this property to publish the compile definitions "
+     "required to compile against the headers for the target.  Consuming "
+     "targets can add entries to their own COMPILE_DEFINITIONS property such "
+     "as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_DEFINITIONS> to use the "
+     "compile definitions specified in the interface of 'foo'."
+     "\n"
+     CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+
+  cm->DefineProperty
     ("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET,
      "Repetition count for STATIC libraries with cyclic dependencies.",
      "When linking to a STATIC library target with cyclic dependencies the "
diff --git a/Tests/ExportImport/Export/CMakeLists.txt 
b/Tests/ExportImport/Export/CMakeLists.txt
index e19ab88..569845a 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -90,9 +90,82 @@ set_property(TARGET testLibCycleA PROPERTY 
LINK_INTERFACE_MULTIPLICITY 3)
 # Test exporting dependent libraries into different exports
 add_library(testLibRequired testLibRequired.c)
 add_library(testLibDepends testLibDepends.c)
+set_property(TARGET testLibDepends APPEND PROPERTY
+  INCLUDE_DIRECTORIES
+    $<TARGET_PROPERTY:testLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
+)
+set_property(TARGET testLibDepends APPEND PROPERTY
+  COMPILE_DEFINITIONS
+    $<TARGET_PROPERTY:testLibRequired,INTERFACE_COMPILE_DEFINITIONS>
+)
+set_property(TARGET testLibDepends APPEND PROPERTY
+  INTERFACE_INCLUDE_DIRECTORIES
+    $<TARGET_PROPERTY:testLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
+)
+set_property(TARGET testLibDepends APPEND PROPERTY
+  INTERFACE_COMPILE_DEFINITIONS
+    $<TARGET_PROPERTY:testLibRequired,INTERFACE_COMPILE_DEFINITIONS>
+)
 target_link_libraries(testLibDepends testLibRequired)
 
-install(TARGETS testLibRequired EXPORT RequiredExp DESTINATION lib )
+macro(add_include_lib _libName)
+  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c" "// no content\n")
+  add_library(${_libName} "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c")
+  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_libName}")
+  set_property(TARGET ${_libName} APPEND PROPERTY
+      INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/${_libName}")
+  if (NOT "${ARGV1}" STREQUAL "NO_HEADER")
+      file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}/${_libName}.h" "// 
no content\n")
+  endif()
+endmacro()
+
+add_include_lib(testLibIncludeRequired1)
+add_include_lib(testLibIncludeRequired2)
+add_include_lib(testLibIncludeRequired3 NO_HEADER)
+# Generate testLibIncludeRequired4 in the testLibIncludeRequired3 directory
+# with an error. If the includes from testLibIncludeRequired3 appear first,
+# the error will be hit.
+# Below, the '3' library appears before the '4' library
+# but we are testing that the INSTALL_INTERFACE causes it not to be used
+# at build time.
+file(WRITE 
"${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired3/testLibIncludeRequired4.h" 
"#error Should not be included\n")
+add_include_lib(testLibIncludeRequired4)
+add_include_lib(testLibIncludeRequired5 NO_HEADER)
+# Generate testLibIncludeRequired6 in the testLibIncludeRequired5 directory
+# with an error. If the includes from testLibIncludeRequired5 appear first,
+# the error will be hit.
+# Below, the '5' library appears before the '6' library
+# but we are testing that when the installed IMPORTED target is used, from
+# the Import side of this unit test, the '6' include from the '5' directory
+# will not be used because it is in the BUILD_INTERFACE only.
+file(WRITE 
"${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired5/testLibIncludeRequired6.h" 
"#error Should not be included\n")
+add_include_lib(testLibIncludeRequired6)
+
+set_property(TARGET testLibRequired APPEND PROPERTY
+  INTERFACE_INCLUDE_DIRECTORIES
+    $<TARGET_PROPERTY:testLibIncludeRequired1,INTERFACE_INCLUDE_DIRECTORIES>
+    
$<TARGET_PROPERTY:$<1:$<TARGET_NAME:testLibIncludeRequired2>>,INTERFACE_INCLUDE_DIRECTORIES>
+    
$<INSTALL_INTERFACE:$<TARGET_PROPERTY:testLibIncludeRequired3,INTERFACE_INCLUDE_DIRECTORIES>>
+    
$<BUILD_INTERFACE:$<TARGET_PROPERTY:testLibIncludeRequired4,INTERFACE_INCLUDE_DIRECTORIES>>
+    
$<BUILD_INTERFACE:$<TARGET_PROPERTY:testLibIncludeRequired5,INTERFACE_INCLUDE_DIRECTORIES>>
+    
$<INSTALL_INTERFACE:$<TARGET_PROPERTY:testLibIncludeRequired6,INTERFACE_INCLUDE_DIRECTORIES>>
+)
+
+set_property(TARGET testLibRequired APPEND PROPERTY
+  INTERFACE_COMPILE_DEFINITIONS
+    testLibRequired_IFACE_DEFINE
+    $<BUILD_INTERFACE:BuildOnly_DEFINE>
+    $<INSTALL_INTERFACE:InstallOnly_DEFINE>
+)
+
+install(TARGETS testLibRequired
+                testLibIncludeRequired1
+                testLibIncludeRequired2
+                testLibIncludeRequired3
+                testLibIncludeRequired4
+                testLibIncludeRequired5
+                testLibIncludeRequired6
+        EXPORT RequiredExp DESTINATION lib )
 install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake 
DESTINATION lib/cmake/testLibRequired)
 
 install(TARGETS testLibDepends EXPORT DependsExp DESTINATION lib )
diff --git a/Tests/ExportImport/Export/testLibDepends.c 
b/Tests/ExportImport/Export/testLibDepends.c
index 2849b33..fb5a002 100644
--- a/Tests/ExportImport/Export/testLibDepends.c
+++ b/Tests/ExportImport/Export/testLibDepends.c
@@ -1,4 +1,20 @@
 
+#include "testLibIncludeRequired1.h"
+#include "testLibIncludeRequired2.h"
+#include "testLibIncludeRequired4.h"
+
+#ifndef testLibRequired_IFACE_DEFINE
+#error Expected testLibRequired_IFACE_DEFINE
+#endif
+
+#ifndef BuildOnly_DEFINE
+#error Expected BuildOnly_DEFINE
+#endif
+
+#ifdef InstallOnly_DEFINE
+#error Unexpected InstallOnly_DEFINE
+#endif
+
 extern int testLibRequired(void);
 
 int testLibDepends(void) { return testLibRequired(); }
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt 
b/Tests/ExportImport/Import/A/CMakeLists.txt
index 8841792..b77562e 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -152,3 +152,18 @@ check_function_exists(testLib1 HAVE_TESTLIB1_FUNCTION)
 if (NOT HAVE_TESTLIB1_FUNCTION)
   message(SEND_ERROR "Using imported target testLib2 in 
check_function_exists() failed !")
 endif()
+
+#-----------------------------------------------------------------------------
+# Test that dependent imported targets have usable
+# INTERFACE_COMPILE_DEFINITIONS and INTERFACE_INCLUDE_DIRECTORIES
+
+add_library(deps_iface deps_iface.cpp)
+target_link_libraries(deps_iface testLibsDepends)
+set_property(TARGET deps_iface APPEND PROPERTY
+  COMPILE_DEFINITIONS
+    $<TARGET_PROPERTY:testLibDepends,INTERFACE_COMPILE_DEFINITIONS>
+)
+set_property(TARGET deps_iface APPEND PROPERTY
+  INCLUDE_DIRECTORIES
+    $<TARGET_PROPERTY:testLibDepends,INTERFACE_INCLUDE_DIRECTORIES>
+)
diff --git a/Tests/ExportImport/Import/A/deps_iface.cpp 
b/Tests/ExportImport/Import/A/deps_iface.cpp
new file mode 100644
index 0000000..7190b92
--- /dev/null
+++ b/Tests/ExportImport/Import/A/deps_iface.cpp
@@ -0,0 +1,24 @@
+
+#include "testLibIncludeRequired1.h"
+#include "testLibIncludeRequired2.h"
+#include "testLibIncludeRequired6.h"
+
+#ifndef testLibRequired_IFACE_DEFINE
+#error Expected testLibRequired_IFACE_DEFINE
+#endif
+
+#ifdef BuildOnly_DEFINE
+#error Unexpected BuildOnly_DEFINE
+#endif
+
+#ifndef InstallOnly_DEFINE
+#error Expected InstallOnly_DEFINE
+#endif
+
+extern int testLibDepends(void);
+
+
+int main(int,char **)
+{
+  return testLibDepends();
+}
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt 
b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
index 7cb1b42..63a5492 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
@@ -37,6 +37,37 @@ include_directories("sing$<1:/ting>")
 
 
include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/arguments;${CMAKE_CURRENT_BINARY_DIR}/list>")
 
+create_header(fee)
+create_header(fiy)
+create_header(foh)
+create_header(fum)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp" "#include \"fee.h\"\n")
+add_library(lib1 "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp")
+set_property(TARGET lib1 APPEND PROPERTY INCLUDE_DIRECTORIES 
"${CMAKE_CURRENT_BINARY_DIR}/fee")
+set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES 
"${CMAKE_CURRENT_BINARY_DIR}/fiy")
+set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES 
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:${CMAKE_CURRENT_BINARY_DIR}/foh>")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp" "#include \"fiy.h\"\n")
+add_library(lib2 "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp")
+set_property(TARGET lib2 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES 
"${CMAKE_CURRENT_BINARY_DIR}/fum;$<TARGET_PROPERTY:lib1,INTERFACE_INCLUDE_DIRECTORIES>")
+set_property(TARGET lib2 APPEND PROPERTY INCLUDE_DIRECTORIES 
"$<TARGET_PROPERTY:lib1,INTERFACE_INCLUDE_DIRECTORIES>")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp" "#include 
\"fiy.h\"\n#include \"foh.h\"\n#include \"fum.h\"\nint main(int,char**) { 
return 0; }\n")
+add_executable(exe3 "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp")
+set_property(TARGET exe3 APPEND PROPERTY INCLUDE_DIRECTORIES 
"$<TARGET_PROPERTY:lib2,INTERFACE_INCLUDE_DIRECTORIES>")
+
+# Test cycles
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib3.cpp" "#include 
\"fiy.h\"\n#include \"foh.h\"\n")
+add_library(lib3 "${CMAKE_CURRENT_BINARY_DIR}/lib3.cpp")
+set_property(TARGET lib3 APPEND PROPERTY INCLUDE_DIRECTORIES 
"${CMAKE_CURRENT_BINARY_DIR}/fiy;$<TARGET_PROPERTY:lib4,INTERFACE_INCLUDE_DIRECTORIES>")
+set_property(TARGET lib3 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES 
"${CMAKE_CURRENT_BINARY_DIR}/fiy;$<TARGET_PROPERTY:lib4,INTERFACE_INCLUDE_DIRECTORIES>")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib4.cpp" "#include 
\"fiy.h\"\n#include \"foh.h\"\n")
+add_library(lib4 "${CMAKE_CURRENT_BINARY_DIR}/lib4.cpp")
+set_property(TARGET lib4 APPEND PROPERTY INCLUDE_DIRECTORIES 
"${CMAKE_CURRENT_BINARY_DIR}/foh;$<TARGET_PROPERTY:lib3,INTERFACE_INCLUDE_DIRECTORIES>")
+set_property(TARGET lib4 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES 
"${CMAKE_CURRENT_BINARY_DIR}/foh;$<TARGET_PROPERTY:lib3,INTERFACE_INCLUDE_DIRECTORIES>")
+
 add_library(somelib::withcolons UNKNOWN IMPORTED)
 set_property(TARGET somelib::withcolons PROPERTY IMPORTED_LOCATION 
"${CMAKE_CURRENT_BINARY_DIR}/target")
 set_property(TARGET somelib::withcolons PROPERTY INTERFACE_INCLUDE_DIRECTORIES 
"${CMAKE_CURRENT_BINARY_DIR}/target")

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f5b1980fb27fa902d37856ec3e22daddfeb9d52f
commit f5b1980fb27fa902d37856ec3e22daddfeb9d52f
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Dec 30 22:06:12 2012 +0100
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Jan 5 01:18:37 2013 +0100

    Populate the ExportedTargets member early in GenerateMainFile
    
    The member variable is checked to determine whether to call
    HandleMissingTarget(). As that could be called during the loop in
    the comming commits, ensure that it contains all targets being
    exported.

diff --git a/Source/cmExportBuildFileGenerator.cxx 
b/Source/cmExportBuildFileGenerator.cxx
index cd6a7ab..3e9a9fd 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -22,6 +22,7 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator()
 //----------------------------------------------------------------------------
 bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
 {
+  std::vector<cmTarget*> allTargets;
   {
   std::string expectedTargets;
   std::string sep;
@@ -31,20 +32,10 @@ bool 
cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
     {
     expectedTargets += sep + this->Namespace + (*tei)->GetName();
     sep = " ";
-    }
-
-  this->GenerateExpectedTargetsCode(os, expectedTargets);
-  }
-
-  // Create all the imported targets.
-  for(std::vector<cmTarget*>::const_iterator
-        tei = this->Exports->begin();
-      tei != this->Exports->end(); ++tei)
-    {
     cmTarget* te = *tei;
     if(this->ExportedTargets.insert(te).second)
       {
-      this->GenerateImportTargetCode(os, te);
+      allTargets.push_back(te);
       }
     else
       {
@@ -58,6 +49,18 @@ bool 
cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
       }
     }
 
+  this->GenerateExpectedTargetsCode(os, expectedTargets);
+  }
+
+  // Create all the imported targets.
+  for(std::vector<cmTarget*>::const_iterator
+        tei = allTargets.begin();
+      tei != allTargets.end(); ++tei)
+    {
+    cmTarget* te = *tei;
+    this->GenerateImportTargetCode(os, te);
+    }
+
   // Generate import file content for each configuration.
   for(std::vector<std::string>::const_iterator
         ci = this->Configurations.begin();
diff --git a/Source/cmExportInstallFileGenerator.cxx 
b/Source/cmExportInstallFileGenerator.cxx
index 6ba7d9f..2b7937e 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -39,6 +39,7 @@ std::string 
cmExportInstallFileGenerator::GetConfigImportFileGlob()
 //----------------------------------------------------------------------------
 bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
 {
+  std::vector<cmTarget*> allTargets;
   {
   std::string expectedTargets;
   std::string sep;
@@ -48,20 +49,10 @@ bool 
cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
     {
     expectedTargets += sep + this->Namespace + (*tei)->Target->GetName();
     sep = " ";
-    }
-
-  this->GenerateExpectedTargetsCode(os, expectedTargets);
-  }
-
-  // Create all the imported targets.
-  for(std::vector<cmTargetExport*>::const_iterator
-        tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
-      tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
-    {
     cmTargetExport const* te = *tei;
     if(this->ExportedTargets.insert(te->Target).second)
       {
-      this->GenerateImportTargetCode(os, te->Target);
+      allTargets.push_back(te->Target);
       }
     else
       {
@@ -75,6 +66,18 @@ bool 
cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
       }
     }
 
+  this->GenerateExpectedTargetsCode(os, expectedTargets);
+  }
+
+  // Create all the imported targets.
+  for(std::vector<cmTarget*>::const_iterator
+        tei = allTargets.begin();
+      tei != allTargets.end(); ++tei)
+    {
+    cmTarget* te = *tei;
+    this->GenerateImportTargetCode(os, te);
+    }
+
   // Now load per-configuration properties for them.
   os << "# Load information for each installed configuration.\n"
      << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c67b8124f735e7f96567a276e16969607b300e43
commit c67b8124f735e7f96567a276e16969607b300e43
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Fri Dec 21 15:49:19 2012 +0100
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Jan 5 01:18:36 2013 +0100

    Make cycles in target properties ignored, not an error.
    
    Constructs such as these are an error as they are direct self-references:
    
     set_property(TARGET foo APPEND PROPERTY
       INCLUDE_DIRECTORIES $<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>)
     set_property(TARGET foo APPEND PROPERTY
       INCLUDE_DIRECTORIES $<TARGET_PROPERTY:INCLUDE_DIRECTORIES>)
    
    However, this is an indirect self-reference in a cycle, and not an error:
    
     set_property(TARGET foo APPEND PROPERTY
       INCLUDE_DIRECTORIES $<TARGET_PROPERTY:bar,INCLUDE_DIRECTORIES>)
     set_property(TARGET bar APPEND PROPERTY
       INCLUDE_DIRECTORIES $<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>)

diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx 
b/Source/cmGeneratorExpressionDAGChecker.cxx
index 4a9fc28..2e5b5ae 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -24,13 +24,14 @@ 
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
   : Parent(parent), Target(target), Property(property),
     Content(content), Backtrace(backtrace)
 {
-  this->IsDAG = this->isDAG();
+  this->CheckResult = this->checkGraph();
 }
 
 //----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::check() const
+cmGeneratorExpressionDAGChecker::Result
+cmGeneratorExpressionDAGChecker::check() const
 {
-  return this->IsDAG;
+  return this->CheckResult;
 }
 
 //----------------------------------------------------------------------------
@@ -38,7 +39,7 @@ void cmGeneratorExpressionDAGChecker::reportError(
                   cmGeneratorExpressionContext *context,
                   const std::string &expr)
 {
-  if (this->IsDAG)
+  if (this->CheckResult == DAG)
     {
     return;
     }
@@ -91,16 +92,17 @@ void cmGeneratorExpressionDAGChecker::reportError(
 }
 
 //----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::isDAG() const
+cmGeneratorExpressionDAGChecker::Result
+cmGeneratorExpressionDAGChecker::checkGraph() const
 {
   const cmGeneratorExpressionDAGChecker *parent = this->Parent;
   while (parent)
     {
     if (this->Target == parent->Target && this->Property == parent->Property)
       {
-      return false;
+      return parent->Parent ? CYCLIC_REFERENCE : SELF_REFERENCE;
       }
     parent = parent->Parent;
     }
-  return true;
+  return DAG;
 }
diff --git a/Source/cmGeneratorExpressionDAGChecker.h 
b/Source/cmGeneratorExpressionDAGChecker.h
index ffc84f8..48f26ed 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -25,12 +25,18 @@ struct cmGeneratorExpressionDAGChecker
                                   const GeneratorExpressionContent *content,
                                   cmGeneratorExpressionDAGChecker *parent);
 
-  bool check() const;
+  enum Result {
+    DAG,
+    SELF_REFERENCE,
+    CYCLIC_REFERENCE
+  };
+
+  Result check() const;
 
   void reportError(cmGeneratorExpressionContext *context,
                    const std::string &expr);
 private:
-  bool isDAG() const;
+  Result checkGraph() const;
 
 private:
   const cmGeneratorExpressionDAGChecker * const Parent;
@@ -38,7 +44,7 @@ private:
   const std::string Property;
   const GeneratorExpressionContent * const Content;
   const cmListFileBacktrace Backtrace;
-  bool IsDAG;
+  Result CheckResult;
 };
 
 #endif
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx 
b/Source/cmGeneratorExpressionEvaluator.cxx
index 8b8b860..4b44ebe 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -381,10 +381,16 @@ static const struct TargetPropertyNode : public 
cmGeneratorExpressionNode
                                                content,
                                                dagCheckerParent);
 
-    if (!dagChecker.check())
+    switch (dagChecker.check())
       {
+    case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
       dagChecker.reportError(context, content->GetOriginalExpression());
       return std::string();
+    case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+      // No error. We just skip cyclic references.
+      return std::string();
+    case cmGeneratorExpressionDAGChecker::DAG:
+      break;
       }
 
     const char *prop = target->GetProperty(propertyName.c_str());

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d0f950fdba88ac08d0e25e340fe558eba008810e
commit d0f950fdba88ac08d0e25e340fe558eba008810e
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Dec 23 11:20:37 2012 +0100
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Jan 5 01:18:36 2013 +0100

    Use mapped config properties to evaluate $<CONFIG>

diff --git a/Source/cmGeneratorExpressionEvaluator.cxx 
b/Source/cmGeneratorExpressionEvaluator.cxx
index 4a7a034..8b8b860 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -265,8 +265,24 @@ static const struct ConfigurationTestNode : public 
cmGeneratorExpressionNode
       return parameters.front().empty() ? "1" : "0";
       }
 
-    return cmsysString_strcasecmp(parameters.begin()->c_str(),
-                                  context->Config) == 0 ? "1" : "0";
+    if (cmsysString_strcasecmp(parameters.begin()->c_str(),
+                                  context->Config) == 0)
+      {
+      return "1";
+      }
+
+    if (context->CurrentTarget
+        && context->CurrentTarget->IsImported())
+      {
+      const char* loc = 0;
+      const char* imp = 0;
+      std::string suffix;
+      return context->CurrentTarget->GetMappedConfig(context->Config,
+                                                  &loc,
+                                                  &imp,
+                                                  suffix) ? "1" : "0";
+      }
+    return "0";
   }
 } configurationTestNode;
 
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 58fab80..d60979c 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -4365,27 +4365,15 @@ cmTarget::GetImportInfo(const char* config)
   return &i->second;
 }
 
-//----------------------------------------------------------------------------
-void cmTarget::ComputeImportInfo(std::string const& desired_config,
-                                 ImportInfo& info)
+bool cmTarget::GetMappedConfig(std::string const& desired_config,
+                               const char** loc,
+                               const char** imp,
+                               std::string& suffix)
 {
-  // This method finds information about an imported target from its
-  // properties.  The "IMPORTED_" namespace is reserved for properties
-  // defined by the project exporting the target.
-
-  // Initialize members.
-  info.NoSOName = false;
-
   // Track the configuration-specific property suffix.
-  std::string suffix = "_";
+  suffix = "_";
   suffix += desired_config;
 
-  // On a DLL platform there may be only IMPORTED_IMPLIB for a shared
-  // library or an executable with exports.
-  bool allowImp = this->HasImportLibrary();
-
-  // Look for a mapping from the current project's configuration to
-  // the imported project's configuration.
   std::vector<std::string> mappedConfigs;
   {
   std::string mapProp = "MAP_IMPORTED_CONFIG_";
@@ -4396,26 +4384,29 @@ void cmTarget::ComputeImportInfo(std::string const& 
desired_config,
     }
   }
 
+  // If we needed to find one of the mapped configurations but did not
+  // On a DLL platform there may be only IMPORTED_IMPLIB for a shared
+  // library or an executable with exports.
+  bool allowImp = this->HasImportLibrary();
+
   // If a mapping was found, check its configurations.
-  const char* loc = 0;
-  const char* imp = 0;
   for(std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
-      !loc && !imp && mci != mappedConfigs.end(); ++mci)
+      !*loc && !*imp && mci != mappedConfigs.end(); ++mci)
     {
     // Look for this configuration.
     std::string mcUpper = cmSystemTools::UpperCase(mci->c_str());
     std::string locProp = "IMPORTED_LOCATION_";
     locProp += mcUpper;
-    loc = this->GetProperty(locProp.c_str());
+    *loc = this->GetProperty(locProp.c_str());
     if(allowImp)
       {
       std::string impProp = "IMPORTED_IMPLIB_";
       impProp += mcUpper;
-      imp = this->GetProperty(impProp.c_str());
+      *imp = this->GetProperty(impProp.c_str());
       }
 
     // If it was found, use it for all properties below.
-    if(loc || imp)
+    if(*loc || *imp)
       {
       suffix = "_";
       suffix += mcUpper;
@@ -4425,45 +4416,45 @@ void cmTarget::ComputeImportInfo(std::string const& 
desired_config,
   // If we needed to find one of the mapped configurations but did not
   // then the target is not found.  The project does not want any
   // other configuration.
-  if(!mappedConfigs.empty() && !loc && !imp)
+  if(!mappedConfigs.empty() && !*loc && !*imp)
     {
-    return;
+    return false;
     }
 
   // If we have not yet found it then there are no mapped
   // configurations.  Look for an exact-match.
-  if(!loc && !imp)
+  if(!*loc && !*imp)
     {
     std::string locProp = "IMPORTED_LOCATION";
     locProp += suffix;
-    loc = this->GetProperty(locProp.c_str());
+    *loc = this->GetProperty(locProp.c_str());
     if(allowImp)
       {
       std::string impProp = "IMPORTED_IMPLIB";
       impProp += suffix;
-      imp = this->GetProperty(impProp.c_str());
+      *imp = this->GetProperty(impProp.c_str());
       }
     }
 
   // If we have not yet found it then there are no mapped
   // configurations and no exact match.
-  if(!loc && !imp)
+  if(!*loc && !*imp)
     {
     // The suffix computed above is not useful.
     suffix = "";
 
     // Look for a configuration-less location.  This may be set by
     // manually-written code.
-    loc = this->GetProperty("IMPORTED_LOCATION");
+    *loc = this->GetProperty("IMPORTED_LOCATION");
     if(allowImp)
       {
-      imp = this->GetProperty("IMPORTED_IMPLIB");
+      *imp = this->GetProperty("IMPORTED_IMPLIB");
       }
     }
 
   // If we have not yet found it then the project is willing to try
   // any available configuration.
-  if(!loc && !imp)
+  if(!*loc && !*imp)
     {
     std::vector<std::string> availableConfigs;
     if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS"))
@@ -4472,24 +4463,45 @@ void cmTarget::ComputeImportInfo(std::string const& 
desired_config,
       }
     for(std::vector<std::string>::const_iterator
           aci = availableConfigs.begin();
-        !loc && !imp && aci != availableConfigs.end(); ++aci)
+        !*loc && !*imp && aci != availableConfigs.end(); ++aci)
       {
       suffix = "_";
       suffix += cmSystemTools::UpperCase(*aci);
       std::string locProp = "IMPORTED_LOCATION";
       locProp += suffix;
-      loc = this->GetProperty(locProp.c_str());
+      *loc = this->GetProperty(locProp.c_str());
       if(allowImp)
         {
         std::string impProp = "IMPORTED_IMPLIB";
         impProp += suffix;
-        imp = this->GetProperty(impProp.c_str());
+        *imp = this->GetProperty(impProp.c_str());
         }
       }
     }
-
   // If we have not yet found it then the target is not available.
-  if(!loc && !imp)
+  if(!*loc && !*imp)
+    {
+    return false;
+    }
+
+  return true;
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::ComputeImportInfo(std::string const& desired_config,
+                                 ImportInfo& info)
+{
+  // This method finds information about an imported target from its
+  // properties.  The "IMPORTED_" namespace is reserved for properties
+  // defined by the project exporting the target.
+
+  // Initialize members.
+  info.NoSOName = false;
+
+  const char* loc = 0;
+  const char* imp = 0;
+  std::string suffix;
+  if (!this->GetMappedConfig(desired_config, &loc, &imp, suffix))
     {
     return;
     }
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 3f36050..52d5ca6 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -404,6 +404,11 @@ public:
   // Get the properties
   cmPropertyMap &GetProperties() { return this->Properties; };
 
+  bool GetMappedConfig(std::string const& desired_config,
+                       const char** loc,
+                       const char** imp,
+                       std::string& suffix);
+
   // Define the properties
   static void DefineProperties(cmake *cm);
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=26def1771dfbf502129212c9e728e34860477fac
commit 26def1771dfbf502129212c9e728e34860477fac
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Tue Nov 6 16:06:31 2012 +0100
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Jan 5 01:18:36 2013 +0100

    Make all relevant targets available in the genex context.
    
    The current node being evaluated transitively in the generator
    expression must be available to resolve mapped configs.

diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 841fbb7..6d003e1 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -53,7 +53,22 @@ cmGeneratorExpression::~cmGeneratorExpression()
 //----------------------------------------------------------------------------
 const char *cmCompiledGeneratorExpression::Evaluate(
   cmMakefile* mf, const char* config, bool quiet,
-  cmTarget *target,
+  cmTarget *headTarget,
+  cmGeneratorExpressionDAGChecker *dagChecker) const
+{
+  return this->Evaluate(mf,
+                        config,
+                        quiet,
+                        headTarget,
+                        headTarget,
+                        dagChecker);
+}
+
+//----------------------------------------------------------------------------
+const char *cmCompiledGeneratorExpression::Evaluate(
+  cmMakefile* mf, const char* config, bool quiet,
+  cmTarget *headTarget,
+  cmTarget *currentTarget,
   cmGeneratorExpressionDAGChecker *dagChecker) const
 {
   if (!this->NeedsParsing)
@@ -73,7 +88,8 @@ const char *cmCompiledGeneratorExpression::Evaluate(
   context.Config = config;
   context.Quiet = quiet;
   context.HadError = false;
-  context.Target = target;
+  context.HeadTarget = headTarget;
+  context.CurrentTarget = currentTarget ? currentTarget : headTarget;
   context.Backtrace = this->Backtrace;
 
   for ( ; it != end; ++it)
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 99056a5..dcdfefb 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -71,8 +71,13 @@ class cmCompiledGeneratorExpression
 public:
   const char* Evaluate(cmMakefile* mf, const char* config,
                        bool quiet = false,
-                       cmTarget *target = 0,
+                       cmTarget *headTarget = 0,
+                       cmTarget *currentTarget = 0,
                        cmGeneratorExpressionDAGChecker *dagChecker = 0) const;
+  const char* Evaluate(cmMakefile* mf, const char* config,
+                       bool quiet,
+                       cmTarget *headTarget,
+                       cmGeneratorExpressionDAGChecker *dagChecker) const;
 
   /** Get set of targets found during evaluations.  */
   std::set<cmTarget*> const& GetTargets() const
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx 
b/Source/cmGeneratorExpressionDAGChecker.cxx
index bfb0ddf..4a9fc28 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -57,7 +57,7 @@ void cmGeneratorExpressionDAGChecker::reportError(
     e << "Error evaluating generator expression:\n"
       << "  " << expr << "\n"
       << "Self reference on target \""
-      << context->Target->GetName() << "\".\n";
+      << context->HeadTarget->GetName() << "\".\n";
     context->Makefile->GetCMakeInstance()
       ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
                       parent->Backtrace);
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx 
b/Source/cmGeneratorExpressionEvaluator.cxx
index c8f5b82..4a7a034 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -297,7 +297,7 @@ static const struct TargetPropertyNode : public 
cmGeneratorExpressionNode
     cmsys::RegularExpression propertyNameValidator;
     propertyNameValidator.compile("^[A-Za-z0-9_]+$");
 
-    cmTarget* target = context->Target;
+    cmTarget* target = context->HeadTarget;
     std::string propertyName = *parameters.begin();
     if (parameters.size() == 2)
       {
diff --git a/Source/cmGeneratorExpressionEvaluator.h 
b/Source/cmGeneratorExpressionEvaluator.h
index d904b02..59804ff 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -26,7 +26,9 @@ struct cmGeneratorExpressionContext
   std::set<cmTarget*> Targets;
   cmMakefile *Makefile;
   const char *Config;
-  cmTarget *Target;
+  cmTarget *HeadTarget; // The target whose property is being evaluated.
+  cmTarget *CurrentTarget; // The dependent of HeadTarget which appears
+                           // directly or indirectly in the property.
   bool Quiet;
   bool HadError;
 };

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0c657dc637ca4da6861102c7306069ad157ec08d
commit 0c657dc637ca4da6861102c7306069ad157ec08d
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Mon Dec 10 23:05:11 2012 +0100
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Jan 5 01:18:36 2013 +0100

    Add API to populate INTERFACE properties in exported targets.
    
    The INTERFACE properties need to be preprocessed for context (build
    location or install location) and to extract target names etc.

diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 2507b72..2b133be 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -125,6 +125,65 @@ void 
cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
 }
 
 //----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+                      const char *outputName,
+                      cmTarget *target,
+                      cmGeneratorExpression::PreprocessContext preprocessRule,
+                      ImportPropertyMap &properties,
+                      std::vector<std::string> &missingTargets)
+{
+  const char *input = target->GetProperty(propName);
+  if (input)
+    {
+    if (!*input)
+      {
+      // Set to empty
+      properties[outputName] = "";
+      return;
+      }
+
+    std::string prepro = cmGeneratorExpression::Preprocess(input,
+                                                           preprocessRule);
+    if (!prepro.empty())
+      {
+      this->ResolveTargetsInGeneratorExpressions(prepro, target,
+                                                 missingTargets);
+      properties[outputName] = prepro;
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+                      cmTarget *target,
+                      cmGeneratorExpression::PreprocessContext preprocessRule,
+                      ImportPropertyMap &properties,
+                      std::vector<std::string> &missingTargets)
+{
+  this->PopulateInterfaceProperty(propName, propName, target, preprocessRule,
+                            properties, missingTargets);
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
+                                        std::ostream& os,
+                                        const ImportPropertyMap &properties)
+{
+  if (!properties.empty())
+    {
+    std::string targetName = this->Namespace;
+    targetName += target->GetName();
+    os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
+    for(ImportPropertyMap::const_iterator pi = properties.begin();
+        pi != properties.end(); ++pi)
+      {
+      os << "  " << pi->first << " \"" << pi->second << "\"\n";
+      }
+    os << ")\n\n";
+    }
+}
+
+//----------------------------------------------------------------------------
 void
 cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
                                     std::string &input,
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 0b89a64..7c58ad8 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -13,6 +13,7 @@
 #define cmExportFileGenerator_h
 
 #include "cmCommand.h"
+#include "cmGeneratorExpression.h"
 
 /** \class cmExportFileGenerator
  * \brief Generate a file exporting targets from a build or install tree.
@@ -93,6 +94,13 @@ protected:
                                    cmMakefile* mf,
                                    cmTarget* depender,
                                    cmTarget* dependee) = 0;
+  void PopulateInterfaceProperty(const char *,
+                                 cmTarget *target,
+                                 cmGeneratorExpression::PreprocessContext,
+                                 ImportPropertyMap &properties,
+                                 std::vector<std::string> &missingTargets);
+  void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
+                                   const ImportPropertyMap &properties);
 
   void ResolveTargetsInGeneratorExpressions(std::string &input,
                                     cmTarget* target,
@@ -113,6 +121,13 @@ protected:
 
   // The set of targets included in the export.
   std::set<cmTarget*> ExportedTargets;
+
+private:
+  void PopulateInterfaceProperty(const char *, const char *,
+                                 cmTarget *target,
+                                 cmGeneratorExpression::PreprocessContext,
+                                 ImportPropertyMap &properties,
+                                 std::vector<std::string> &missingTargets);
 };
 
 #endif

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e04f737c7a3e66c49e2d50813af1fa40a415eff8
commit e04f737c7a3e66c49e2d50813af1fa40a415eff8
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Mon Dec 10 23:07:09 2012 +0100
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Jan 5 01:18:36 2013 +0100

    Add API to extract target names from a genex string.
    
    The TARGET_NAME expression, which requires a literal, provides
    target names. $<TARGET_PROPERTY:tgt,prop> also provides target
    names in the cases where tgt is a literal, so that TARGET_NAME is
    not needed then in addition.

diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 3f738cc..2507b72 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -126,6 +126,142 @@ void 
cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
 
 //----------------------------------------------------------------------------
 void
+cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
+                                    std::string &input,
+                                    cmTarget* target,
+                                    std::vector<std::string> &missingTargets)
+{
+  std::string::size_type pos = 0;
+  std::string::size_type lastPos = pos;
+
+  cmMakefile *mf = target->GetMakefile();
+  std::string errorString;
+
+  while((pos = input.find("$<TARGET_PROPERTY:", lastPos)) != input.npos)
+    {
+    std::string::size_type nameStartPos = pos +
+                                            sizeof("$<TARGET_PROPERTY:") - 1;
+    std::string::size_type closePos = input.find(">", nameStartPos);
+    std::string::size_type commaPos = input.find(",", nameStartPos);
+    std::string::size_type nextOpenPos = input.find("$<", nameStartPos);
+    if (commaPos == input.npos // Implied 'this' target
+        || closePos == input.npos // Imcomplete expression.
+        || closePos < commaPos // Implied 'this' target
+        || nextOpenPos < commaPos) // Non-literal
+      {
+      lastPos = nameStartPos;
+      continue;
+      }
+
+    const std::string targetName = input.substr(nameStartPos,
+                                                commaPos - nameStartPos);
+
+    pos = nameStartPos; // We're not going to replace the entire expression,
+                        // but only the target parameter.
+    if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str()))
+      {
+      if(tgt->IsImported())
+        {
+        pos += targetName.size();
+        }
+      else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
+        {
+        input.replace(pos, targetName.size(),
+                      this->Namespace + targetName);
+        pos += this->Namespace.size() + targetName.size();
+        }
+      else
+        {
+        std::string namespacedTarget;
+        this->HandleMissingTarget(namespacedTarget, missingTargets,
+                                  mf, target, tgt);
+        if (!namespacedTarget.empty())
+          {
+          input.replace(pos, targetName.size(), namespacedTarget);
+          pos += namespacedTarget.size();
+          }
+        }
+      }
+    else
+      {
+      errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires "
+                    "its first parameter to be a reachable target.";
+      }
+    lastPos = pos;
+    if (!errorString.empty())
+      {
+      break;
+      }
+    }
+  if (!errorString.empty())
+    {
+    mf->IssueMessage(cmake::FATAL_ERROR, errorString);
+    return;
+    }
+
+  pos = 0;
+  lastPos = pos;
+  while((pos = input.find("$<TARGET_NAME:", lastPos)) != input.npos)
+    {
+    std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1;
+    std::string::size_type endPos = input.find(">", nameStartPos);
+    if (endPos == input.npos)
+      {
+      errorString = "$<TARGET_NAME:...> expression incomplete";
+      }
+    const std::string targetName = input.substr(nameStartPos,
+                                                endPos - nameStartPos);
+    if(targetName.find("$<", lastPos) != input.npos)
+      {
+      errorString = "$<TARGET_NAME:...> requires its parameter to be a "
+                    "literal.";
+      }
+    if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str()))
+      {
+      if(tgt->IsImported())
+        {
+        input.replace(pos, sizeof("$<TARGET_NAME:") + targetName.size(),
+                      targetName);
+        pos += sizeof("$<TARGET_NAME:") + targetName.size();
+        }
+      else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
+        {
+        input.replace(pos, sizeof("$<TARGET_NAME:") + targetName.size(),
+                      this->Namespace + targetName);
+        pos += sizeof("$<TARGET_NAME:") + targetName.size();
+        }
+      else
+        {
+        std::string namespacedTarget;
+        this->HandleMissingTarget(namespacedTarget, missingTargets,
+                                  mf, target, tgt);
+        if (!namespacedTarget.empty())
+          {
+          input.replace(pos, sizeof("$<TARGET_NAME:") + targetName.size(),
+                        namespacedTarget);
+          pos += sizeof("$<TARGET_NAME:") + targetName.size();
+          }
+        }
+      }
+    else
+      {
+      errorString = "$<TARGET_NAME:...> requires its parameter to be a "
+                    "reachable target.";
+      }
+    lastPos = pos;
+    if (!errorString.empty())
+      {
+      break;
+      }
+    }
+  if (!errorString.empty())
+    {
+    mf->IssueMessage(cmake::FATAL_ERROR, errorString);
+    }
+}
+
+//----------------------------------------------------------------------------
+void
 cmExportFileGenerator
 ::SetImportDetailProperties(const char* config, std::string const& suffix,
                             cmTarget* target, ImportPropertyMap& properties,
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 4a75c52..0b89a64 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -94,6 +94,10 @@ protected:
                                    cmTarget* depender,
                                    cmTarget* dependee) = 0;
 
+  void ResolveTargetsInGeneratorExpressions(std::string &input,
+                                    cmTarget* target,
+                                    std::vector<std::string> &missingTargets);
+
   // The namespace in which the exports are placed in the generated file.
   std::string Namespace;
 

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

Summary of changes:


hooks/post-receive
-- 
CMake
_______________________________________________
Cmake-commits mailing list
Cmake-commits@cmake.org
http://public.kitware.com/cgi-bin/mailman/listinfo/cmake-commits

Reply via email to