[Cmake-commits] CMake branch, next, updated. v2.8.10.2-1183-g655896e

Brad King brad.king at kitware.com
Mon Dec 3 08:38:25 EST 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  655896e293009d6e62c94914cef3369ce363dfb2 (commit)
       via  6a392199d4b4047712211e0bcc5cce8ff4ea75a9 (commit)
       via  8e9f8b677462e9284c224791d9e06f1f559d31c6 (commit)
       via  88cf651b76fa8793cd5f78cae03ce4af2958425e (commit)
      from  65c52b0b50553ce851579845b2617b64484102b3 (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=655896e293009d6e62c94914cef3369ce363dfb2
commit 655896e293009d6e62c94914cef3369ce363dfb2
Merge: 65c52b0 6a39219
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Dec 3 08:38:22 2012 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Mon Dec 3 08:38:22 2012 -0500

    Merge topic 'add-INTERFACE_LINK_LIBRARIES-property' into next
    
    6a39219 Add INTERFACE_LINK_LIBRARIES property
    8e9f8b6 GenEx: Add the CONFIG_DEBUG expression
    88cf651 GenEx: Add expressions to specify build- or install-only values


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6a392199d4b4047712211e0bcc5cce8ff4ea75a9
commit 6a392199d4b4047712211e0bcc5cce8ff4ea75a9
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu Nov 1 00:32:10 2012 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Dec 3 08:32:38 2012 -0500

    Add INTERFACE_LINK_LIBRARIES property
    
    This new INTERFACE_LINK_LIBRARIES property is a replacement for the
    (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? properties as it can
    contain generator expressions.  It is also part of the generated
    IMPORTED targets generated by the export() and install(EXPORT) commands.
    Do not set or read the new property for STATIC libraries.
    
    User code may already populate the old properties, so add policy CMP0019
    to handle that.  Record the policy setting when a target is created to
    choose which interfaces to make available to consumers of the target:
    
    - In the OLD behavior ignore INTERFACE_LINK_LIBRARIES and provide the
      old interface properties to consumers.
    
    - In the NEW behavior make INTERFACE_LINK_LIBRARIES available to
      consumers and set the old LINK_INTERFACE_LIBRARIES properties only
      when the project set one explicitly.  LINK_PUBLIC no longer sets it.
    
    - If the policy is not set then compare the old and new properties, warn
      if they are different, and use the OLD behavior.
    
    The policy affects only the interface properties provided by a target,
    not which interfaces are used by consumers.  When linking to a target
    (IMPORTED or not) that provides the new INTERFACE_LINK_LIBRARIES, always
    use it.  Fall back to the old LINK_INTERFACE_LIBRARIES properties only
    if they are set and the new one is not.

diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 55d70f8..2502b92 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -1397,6 +1397,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
      false,
      "Variables that Control the Build");
   cm->DefineProperty
+    ("CMAKE_INTERFACE_LINK_LIBRARIES", cmProperty::VARIABLE,
+     "Default value for INTERFACE_LINK_LIBRARIES of targets.",
+     "This variable is used to initialize the "
+     "INTERFACE_LINK_LIBRARIES property on all the targets. "
+     "See that target property for additional information.",
+     false,
+     "Variables that Control the Build");
+  cm->DefineProperty
     ("CMAKE_WIN32_EXECUTABLE", cmProperty::VARIABLE,
      "Default value for WIN32_EXECUTABLE of targets.",
      "This variable is used to initialize the "
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index fb3f39f..3812516 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -12,6 +12,7 @@
 #include "cmExportBuildFileGenerator.h"
 
 #include "cmExportCommand.h"
+#include "cmGeneratorExpression.h"
 
 //----------------------------------------------------------------------------
 cmExportBuildFileGenerator::cmExportBuildFileGenerator()
@@ -31,6 +32,20 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
     if(this->ExportedTargets.insert(te).second)
       {
       this->GenerateImportTargetCode(os, te);
+
+      ImportPropertyMap properties;
+
+      if ((*tei)->GetPolicyStatusCMP0019() == cmPolicies::NEW)
+        {
+        if ((*tei)->GetType() != cmTarget::STATIC_LIBRARY)
+          {
+          this->PopulateInterfaceProperty("INTERFACE_LINK_LIBRARIES", te,
+                                        cmGeneratorExpression::BuildInterface,
+                                        properties);
+          }
+        }
+
+      this->GenerateInterfaceProperties(te, os, properties);
       }
     else
       {
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 8dffae4..a67c3ee 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -125,6 +125,50 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
 }
 
 //----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+                      cmTarget *target,
+                      cmGeneratorExpression::PreprocessContext preprocessRule,
+                      ImportPropertyMap &properties)
+{
+  const char *input = target->GetProperty(propName);
+  if (input)
+    {
+    if (!*input)
+      {
+      // Set to empty
+      properties[propName] = "";
+      return;
+      }
+    std::string prepro = cmGeneratorExpression::Preprocess(input,
+                                                    preprocessRule,
+                                                    this->Namespace.c_str());
+    if (!prepro.empty())
+      {
+      properties[propName] = prepro;
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+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
 ::SetImportDetailProperties(const char* config, std::string const& suffix,
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 70bc65d..3aee1b8 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.
@@ -91,6 +92,12 @@ protected:
                                    cmMakefile* mf,
                                    cmTarget* depender,
                                    cmTarget* dependee) = 0;
+  void PopulateInterfaceProperty(const char *,
+                                 cmTarget *target,
+                                 cmGeneratorExpression::PreprocessContext,
+                                 ImportPropertyMap &properties);
+  void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
+                                   const ImportPropertyMap &properties);
 
   // The namespace in which the exports are placed in the generated file.
   std::string Namespace;
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 7841731..a988f63 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -19,6 +19,7 @@
 #include "cmInstallExportGenerator.h"
 #include "cmInstallTargetGenerator.h"
 #include "cmTargetExport.h"
+#include "cmGeneratorExpression.h"
 
 //----------------------------------------------------------------------------
 cmExportInstallFileGenerator
@@ -48,6 +49,21 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
     if(this->ExportedTargets.insert(te->Target).second)
       {
       this->GenerateImportTargetCode(os, te->Target);
+
+      ImportPropertyMap properties;
+
+      if ((*tei)->Target->GetPolicyStatusCMP0019() == cmPolicies::NEW)
+        {
+        if (te->Target->GetType() != cmTarget::STATIC_LIBRARY)
+          {
+          this->PopulateInterfaceProperty("INTERFACE_LINK_LIBRARIES",
+                                      te->Target,
+                                      cmGeneratorExpression::InstallInterface,
+                                      properties);
+          }
+        }
+
+      this->GenerateInterfaceProperties(te->Target, os, properties);
       }
     else
       {
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 6aef502..304904a 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -491,6 +491,53 @@ cmPolicies::cmPolicies()
     "CMAKE_SHARED_LIBRARY_<Lang>_FLAGS whether it is modified or not and "
     "honor the POSITION_INDEPENDENT_CODE target property.",
     2,8,9,0, cmPolicies::WARN);
+
+    this->DefinePolicy(
+    CMP0019, "CMP0019",
+    "Use INTERFACE_LINK_LIBRARIES instead of LINK_INTERFACE_LIBRARIES.",
+    "A CMake shared library target (or an executable with the "
+    "ENABLE_EXPORTS property) may be given a \"link interface\" "
+    "determining the libraries that must be linked by its dependents.  "
+    "CMake 2.8.10 and lower used the LINK_INTERFACE_LIBRARIES and "
+    "LINK_INTERFACE_LIBRARIES_<CONFIG> target properties "
+    "to determine the link interface.  "
+    "CMake 2.8.11 and higher prefer the single "
+    "INTERFACE_LINK_LIBRARIES target property "
+    "to determine the link interface.  "
+    "The new property supports generator expressions "
+    "to specify configuration-specific link libraries."
+    "\n"
+    "This policy is not considered when loading IMPORTED targets.  "
+    "However, it does affect how the export() and install(EXPORT) "
+    "commands generate imported targets for use in dependent projects.  "
+    "\n"
+    "The OLD behavior for this policy is to ignore the new "
+    "INTERFACE_LINK_LIBRARIES property and use the old "
+    "LINK_INTERFACE_LIBRARIES(_<CONFIG>) properties to determine the "
+    "link interface.  "
+    "Targets named after LINK_PUBLIC in target_link_libraries will "
+    "populate the old properties and the new.  "
+    "The export() and install(EXPORT) commands will generate only the "
+    "IMPORTED_LINK_INTERFACE_LIBRARIES(_<CONFIG>) properties on a "
+    "target to be imported into other projects, and not "
+    "INTERFACE_LINK_LIBRARIES.  "
+    "\n"
+    "The NEW behavior for this policy is to ignore the old "
+    "LINK_INTERFACE_LIBRARIES(_<CONFIG>) properties and use the new "
+    "INTERFACE_LINK_LIBRARIES property to determine the link interface.  "
+    "Targets named after LINK_PUBLIC in target_link_libraries will "
+    "populate the new property and not the old.  "
+    "The export() and install(EXPORT) commands will generate the new "
+    "INTERFACE_LINK_LIBRARIES property on a target to be imported "
+    "into other projects.  "
+    "They will generate IMPORTED_LINK_INTERFACE_LIBRARIES(_<CONFIG>) "
+    "properties only if LINK_INTERFACE_LIBRARIES(_<CONFIG>) have been "
+    "set explicitly on the target to be exported."
+    "\n"
+    "The setting for this policy used to determine the link interface is "
+    "that in effect when the target is created by an add_library or "
+    "add_executable command.",
+    2,8,11,0, cmPolicies::WARN);
 }
 
 cmPolicies::~cmPolicies()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 6932565..b6b8e39 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -68,6 +68,7 @@ public:
     CMP0018, ///< Ignore language flags for shared libs, and adhere to
     /// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
     /// instead.
+    CMP0019, ///< Use new-style INTERFACE_LINK_LIBRARIES
 
     /** \brief Always the last entry.
      *
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index be20464..723e721 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -21,6 +21,7 @@
 #include "cmDocumentLocationUndefined.h"
 #include "cmListFileCache.h"
 #include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
 #include <cmsys/RegularExpression.hxx>
 #include <map>
 #include <set>
@@ -127,6 +128,7 @@ cmTarget::cmTarget()
   this->PolicyStatusCMP0003 = cmPolicies::WARN;
   this->PolicyStatusCMP0004 = cmPolicies::WARN;
   this->PolicyStatusCMP0008 = cmPolicies::WARN;
+  this->PolicyStatusCMP0019 = cmPolicies::WARN;
   this->LinkLibrariesAnalyzed = false;
   this->HaveInstallRule = false;
   this->DLLPlatform = false;
@@ -371,7 +373,7 @@ void cmTarget::DefineProperties(cmake *cm)
      "imported library.  "
      "The list "
      "should be disjoint from the list of interface libraries in the "
-     "IMPORTED_LINK_INTERFACE_LIBRARIES property.  On platforms requiring "
+     "INTERFACE_LINK_LIBRARIES property.  On platforms requiring "
      "dependent shared libraries to be found at link time CMake uses this "
      "list to add appropriate files or paths to the link command line.  "
      "Ignored for non-imported targets.");
@@ -392,7 +394,9 @@ void cmTarget::DefineProperties(cmake *cm)
      "The libraries will be included on the link line for the target.  "
      "Unlike the LINK_INTERFACE_LIBRARIES property, this property applies "
      "to all imported target types, including STATIC libraries.  "
-     "This property is ignored for non-imported targets.");
+     "This property is ignored for non-imported targets.\n"
+     "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead."
+    );
 
   cm->DefineProperty
     ("IMPORTED_LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET,
@@ -400,7 +404,8 @@ void cmTarget::DefineProperties(cmake *cm)
      "Configuration names correspond to those provided by the project "
      "from which the target is imported.  "
      "If set, this property completely overrides the generic property "
-     "for the named configuration.");
+     "for the named configuration."
+     "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
 
   cm->DefineProperty
     ("IMPORTED_LINK_INTERFACE_LANGUAGES", cmProperty::TARGET,
@@ -700,7 +705,8 @@ void cmTarget::DefineProperties(cmake *cm)
      "This property is initialized by the value of the variable "
      "CMAKE_LINK_INTERFACE_LIBRARIES if it is set when a target is "
      "created.  "
-     "This property is ignored for STATIC libraries.");
+     "This property is ignored for STATIC libraries."
+     "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
 
   cm->DefineProperty
     ("LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET,
@@ -708,7 +714,30 @@ void cmTarget::DefineProperties(cmake *cm)
      "This is the configuration-specific version of "
      "LINK_INTERFACE_LIBRARIES.  "
      "If set, this property completely overrides the generic property "
-     "for the named configuration.");
+     "for the named configuration."
+     "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
+
+  cm->DefineProperty
+    ("INTERFACE_LINK_LIBRARIES", cmProperty::TARGET,
+     "List public interface libraries for a shared library or executable.",
+     "By default linking to a shared library target transitively "
+     "links to targets with which the library itself was linked.  "
+     "For an executable with exports (see the ENABLE_EXPORTS property) "
+     "no default transitive link dependencies are used.  "
+     "This property replaces the default transitive link dependencies with "
+     "an explicit list.  "
+     "When the target is linked into another target the libraries "
+     "listed (and recursively their link interface libraries) will be "
+     "provided to the other target also.  "
+     "If the list is empty then no transitive link dependencies will be "
+     "incorporated when this target is linked into another target even if "
+     "the default set is non-empty.  "
+     "This property is initialized by the value of the variable "
+     "CMAKE_INTERFACE_LINK_LIBRARIES if it is set when a target is "
+     "created.  "
+     "This property is ignored for STATIC libraries."
+     "\n"
+     CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
 
   cm->DefineProperty
     ("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET,
@@ -1348,6 +1377,10 @@ void cmTarget::SetMakefile(cmMakefile* mf)
   this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0);
   this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", 0);
   this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0);
+  if (this->GetType() != STATIC_LIBRARY)
+    {
+    this->SetPropertyDefault("INTERFACE_LINK_LIBRARIES", 0);
+    }
   this->SetPropertyDefault("WIN32_EXECUTABLE", 0);
   this->SetPropertyDefault("MACOSX_BUNDLE", 0);
 
@@ -1409,6 +1442,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
     this->Makefile->GetPolicyStatus(cmPolicies::CMP0004);
   this->PolicyStatusCMP0008 =
     this->Makefile->GetPolicyStatus(cmPolicies::CMP0008);
+  this->PolicyStatusCMP0019 =
+    this->Makefile->GetPolicyStatus(cmPolicies::CMP0019);
 }
 
 //----------------------------------------------------------------------------
@@ -2504,6 +2539,29 @@ void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
 }
 
 //----------------------------------------------------------------------------
+static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
+                                                  cmMakefile* context)
+{
+  // Look for link-type keywords in the value.
+  static cmsys::RegularExpression
+    keys("(^|;)(debug|optimized|general)(;|$)");
+  if(!keys.find(value))
+    {
+    return;
+    }
+
+  // Report an error.
+  cmOStringStream e;
+
+  e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type "
+    "keyword \"" << keys.match(2) << "\".  The INTERFACE_LINK_LIBRARIES "
+    "property may contain configuration-sensitive generator-expressions "
+    "which may be used to specify per-configuration rules.";
+
+  context->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
 static void cmTargetCheckLINK_INTERFACE_LIBRARIES(
   const char* prop, const char* value, cmMakefile* context, bool imported
   )
@@ -2564,6 +2622,13 @@ void cmTarget::CheckProperty(const char* prop, cmMakefile* context)
       cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true);
       }
     }
+  if(strncmp(prop, "INTERFACE_LINK_LIBRARIES", 24) == 0)
+    {
+    if(const char* value = this->GetProperty(prop))
+      {
+      cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context);
+      }
+    }
 }
 
 //----------------------------------------------------------------------------
@@ -4238,6 +4303,28 @@ cmTarget::GetImportInfo(const char* config)
   return &i->second;
 }
 
+
+bool handleCMP0019(const std::vector<std::string> &newLinkLibraries,
+  const std::vector<std::string> &oldLinkLibraries)
+{
+  if (newLinkLibraries.size() != oldLinkLibraries.size())
+    {
+    return false;
+    }
+  for(std::vector<std::string>::const_iterator
+      oll = oldLinkLibraries.begin(), nll = newLinkLibraries.begin();
+      oll != oldLinkLibraries.end() && nll != newLinkLibraries.end();
+      ++oll, ++nll)
+    {
+    if (*oll != *nll)
+      {
+      return false;
+      }
+    }
+  return true;
+}
+
+
 //----------------------------------------------------------------------------
 void cmTarget::ComputeImportInfo(std::string const& desired_config,
                                  ImportInfo& info)
@@ -4440,21 +4527,39 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
     }
 
   // Get the link interface.
-  {
-  std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
-  linkProp += suffix;
-  if(const char* config_libs = this->GetProperty(linkProp.c_str()))
-    {
-    cmSystemTools::ExpandListArgument(config_libs,
+  if(const char* newStyleLibsProp =
+     this->GetProperty("INTERFACE_LINK_LIBRARIES"))
+    {
+    cmListFileBacktrace lfbt;
+    cmGeneratorExpression ge(lfbt);
+
+    cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+                                        this->GetName(),
+                                        "INTERFACE_LINK_LIBRARIES", 0, 0);
+    cmSystemTools::ExpandListArgument(ge.Parse(newStyleLibsProp)
+                                        .Evaluate(this->Makefile,
+                                                  desired_config.c_str(),
+                                                  false,
+                                                  this,
+                                                  &dagChecker),
                                       info.LinkInterface.Libraries);
     }
-  else if(const char* libs =
-          this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES"))
+  else
     {
-    cmSystemTools::ExpandListArgument(libs,
-                                      info.LinkInterface.Libraries);
+    std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
+    linkProp += suffix;
+    if(const char* config_libs = this->GetProperty(linkProp.c_str()))
+      {
+      cmSystemTools::ExpandListArgument(config_libs,
+                                        info.LinkInterface.Libraries);
+      }
+    else if(const char* libs =
+            this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES"))
+      {
+      cmSystemTools::ExpandListArgument(libs,
+                                        info.LinkInterface.Libraries);
+      }
     }
-  }
 
   // Get the link dependencies.
   {
@@ -4562,19 +4667,84 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
 
   // An explicit list of interface libraries may be set for shared
   // libraries and executables that export symbols.
-  const char* explicitLibraries = 0;
+  std::vector<std::string>* explicitLibraries = 0;
+  std::vector<std::string> oldInterfaceLibs;
+  std::vector<std::string> newInterfaceLibs;
   if(this->GetType() == cmTarget::SHARED_LIBRARY ||
      this->IsExecutableWithExports())
     {
-    // Lookup the per-configuration property.
-    std::string propName = "LINK_INTERFACE_LIBRARIES";
-    propName += suffix;
-    explicitLibraries = this->GetProperty(propName.c_str());
+    std::string oldPropName;
+    const char *oldLibrariesProp = 0;
+    const char *newLibrariesProp = 0;
+    if(this->PolicyStatusCMP0019 == cmPolicies::OLD ||
+       this->PolicyStatusCMP0019 == cmPolicies::WARN)
+      {
+      // Lookup the per-configuration property.
+      std::string propName = "LINK_INTERFACE_LIBRARIES";
+      propName += suffix;
+      oldLibrariesProp = this->GetProperty(propName.c_str());
+
+      // If not set, try the generic property.
+      if(!oldLibrariesProp)
+        {
+        oldLibrariesProp = this->GetProperty("LINK_INTERFACE_LIBRARIES");
+        oldPropName = "LINK_INTERFACE_LIBRARIES";
+        }
+      else
+        {
+        oldPropName = propName;
+        }
+      if(oldLibrariesProp)
+        {
+        cmSystemTools::ExpandListArgument(oldLibrariesProp, oldInterfaceLibs);
+        }
+      }
+    if(this->PolicyStatusCMP0019 != cmPolicies::OLD)
+      {
+      newLibrariesProp = this->GetProperty("INTERFACE_LINK_LIBRARIES");
+      if(newLibrariesProp)
+        {
+        cmListFileBacktrace lfbt;
+        cmGeneratorExpression ge(lfbt);
+        cmGeneratorExpressionDAGChecker dagChecker(
+          lfbt, this->GetName(), "INTERFACE_LINK_LIBRARIES", 0, 0);
+        cmSystemTools::ExpandListArgument(ge.Parse(newLibrariesProp).Evaluate(
+                                            this->Makefile,
+                                            config,
+                                            false,
+                                            this,
+                                            &dagChecker), newInterfaceLibs);
+        }
+      }
 
-    // If not set, try the generic property.
-    if(!explicitLibraries)
+    switch (this->PolicyStatusCMP0019)
       {
-      explicitLibraries = this->GetProperty("LINK_INTERFACE_LIBRARIES");
+      case cmPolicies::WARN:
+        {
+        if (newLibrariesProp && oldLibrariesProp
+            && !handleCMP0019(newInterfaceLibs, oldInterfaceLibs))
+          {
+          cmOStringStream e;
+          e << "The INTERFACE_LINK_LIBRARIES and " << oldPropName << " are "
+               "not the same for target \"" << this->GetName() << "\".\n"
+               "NEW content is \""
+            << (newLibrariesProp ? newLibrariesProp : "(unset)") << "\"\n"
+               "OLD content is \""
+            << (oldLibrariesProp ? oldLibrariesProp : "(unset)") << "\"\n"
+            << this->Makefile->GetPolicies()->GetPolicyWarning(
+                                                      cmPolicies::CMP0019);
+          this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+          }
+          // fall through to OLD behaviour
+        }
+        case cmPolicies::OLD:
+          explicitLibraries = oldLibrariesProp ? &oldInterfaceLibs : 0;
+          break;
+        case cmPolicies::REQUIRED_IF_USED:
+        case cmPolicies::REQUIRED_ALWAYS:
+        case cmPolicies::NEW:
+        default:
+          explicitLibraries = newLibrariesProp ? &newInterfaceLibs : 0;
       }
     }
 
@@ -4592,7 +4762,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
   if(explicitLibraries)
     {
     // The interface libraries have been explicitly set.
-    cmSystemTools::ExpandListArgument(explicitLibraries, iface.Libraries);
+    iface.Libraries = *explicitLibraries;
 
     if(this->GetType() == cmTarget::SHARED_LIBRARY)
       {
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 9efd638..7c55933 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -99,6 +99,10 @@ public:
   cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const
     { return this->PolicyStatusCMP0008; }
 
+  /** Get the status of policy CMP0019 when the target was created.  */
+  cmPolicies::PolicyStatus GetPolicyStatusCMP0019() const
+    { return this->PolicyStatusCMP0019; }
+
   /**
    * Get the list of the custom commands for this target
    */
@@ -618,6 +622,7 @@ private:
   cmPolicies::PolicyStatus PolicyStatusCMP0003;
   cmPolicies::PolicyStatus PolicyStatusCMP0004;
   cmPolicies::PolicyStatus PolicyStatusCMP0008;
+  cmPolicies::PolicyStatus PolicyStatusCMP0019;
 
   // Internal representation details.
   friend class cmTargetInternals;
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index f42b0f6..68565db 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -232,7 +232,14 @@ bool cmTargetLinkLibrariesCommand
     {
     this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
     }
-
+  if(this->CurrentProcessingState != ProcessingLinkLibraries &&
+     !this->Target->GetProperty("INTERFACE_LINK_LIBRARIES"))
+    {
+    if (this->Target->GetType() != cmTarget::STATIC_LIBRARY)
+      {
+      this->Target->SetProperty("INTERFACE_LINK_LIBRARIES", "");
+      }
+    }
   return true;
 }
 
@@ -250,6 +257,25 @@ cmTargetLinkLibrariesCommand
 }
 
 //----------------------------------------------------------------------------
+static std::string generatorIface(const std::string &value,
+                                  cmTarget::LinkLibraryType llt)
+{
+  if (llt == cmTarget::DEBUG)
+    {
+    return "$<$<CONFIG_DEBUG>:"
+                     + value
+                     + ">";
+    }
+  else if (llt == cmTarget::OPTIMIZED)
+    {
+    return "$<$<NOT:$<CONFIG_DEBUG>>:"
+                     + value
+                     + ">";
+    }
+  return value;
+}
+
+//----------------------------------------------------------------------------
 void
 cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
                                             cmTarget::LinkLibraryType llt)
@@ -266,6 +292,12 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
       }
     }
 
+  if (this->Target->GetType() != cmTarget::STATIC_LIBRARY)
+    {
+    this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
+                                 generatorIface(lib, llt).c_str());
+    }
+
   // Get the list of configurations considered to be DEBUG.
   std::vector<std::string> const& debugConfigs =
     this->Makefile->GetCMakeInstance()->GetDebugConfigs();
diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
index 1faa888..95cfd15 100644
--- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
@@ -56,3 +56,21 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "")
 target_link_libraries(targetA depB depC)
 
 assert_property(targetA LINK_INTERFACE_LIBRARIES "")
+
+# cmake_policy(PUSH)
+
+cmake_policy(SET CMP0019 NEW)
+
+add_library(depD SHARED depD.cpp)
+generate_export_header(depD)
+set_property(TARGET depD APPEND PROPERTY INTERFACE_LINK_LIBRARIES $<1:depA>)
+
+add_library(depE SHARED depE.cpp)
+generate_export_header(depE)
+target_link_libraries(depE LINK_PRIVATE depB)
+target_link_libraries(depE LINK_INTERFACE_LIBRARIES $<1:depB>)
+
+add_executable(targetB targetB.cpp)
+target_link_libraries(targetB depD depE)
+
+# cmake_policy(POP)
diff --git a/Tests/CMakeCommands/target_link_libraries/depD.cpp b/Tests/CMakeCommands/target_link_libraries/depD.cpp
new file mode 100644
index 0000000..b02c76c
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depD.cpp
@@ -0,0 +1,13 @@
+
+#include "depD.h"
+
+int DepD::foo()
+{
+  return 0;
+}
+
+DepA DepD::getA()
+{
+  DepA a;
+  return a;
+}
diff --git a/Tests/CMakeCommands/target_link_libraries/depD.h b/Tests/CMakeCommands/target_link_libraries/depD.h
new file mode 100644
index 0000000..d24ff5f
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depD.h
@@ -0,0 +1,11 @@
+
+#include "depd_export.h"
+
+#include "depA.h"
+
+struct DEPD_EXPORT DepD
+{
+  int foo();
+
+  DepA getA();
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/depE.cpp b/Tests/CMakeCommands/target_link_libraries/depE.cpp
new file mode 100644
index 0000000..1a3da4a
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depE.cpp
@@ -0,0 +1,13 @@
+
+#include "depE.h"
+
+int DepE::foo()
+{
+  return 0;
+}
+
+DepB DepE::getB()
+{
+  DepB a;
+  return a;
+}
diff --git a/Tests/CMakeCommands/target_link_libraries/depE.h b/Tests/CMakeCommands/target_link_libraries/depE.h
new file mode 100644
index 0000000..2273e17
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depE.h
@@ -0,0 +1,11 @@
+
+#include "depe_export.h"
+
+#include "depB.h"
+
+struct DEPE_EXPORT DepE
+{
+  int foo();
+
+  DepB getB();
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/targetB.cpp b/Tests/CMakeCommands/target_link_libraries/targetB.cpp
new file mode 100644
index 0000000..c6a1264
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/targetB.cpp
@@ -0,0 +1,14 @@
+
+#include "depD.h"
+#include "depE.h"
+
+int main(int argc, char **argv)
+{
+  DepD d;
+  DepA a = d.getA();
+
+  DepE e;
+  DepB b = e.getB();
+
+  return d.foo() + a.foo() + e.foo() + b.foo();
+}

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8e9f8b677462e9284c224791d9e06f1f559d31c6
commit 8e9f8b677462e9284c224791d9e06f1f559d31c6
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Dec 2 09:18:27 2012 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Dec 3 08:30:52 2012 -0500

    GenEx: Add the CONFIG_DEBUG expression
    
    Expand $<CONFIG_DEBUG> to '1' for "debug" configurations (according to
    the DEBUG_CONFIGURATIONS global property) or '0' otherwise.  This is
    equivalent to the "debug" keyword in target_link_libraries.

diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 2899e05..60ff89b 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -19,6 +19,8 @@
   "  $<0:...>                  = empty string (ignores \"...\")\n"      \
   "  $<1:...>                  = content of \"...\"\n"                  \
   "  $<CONFIG:cfg>             = '1' if config is \"cfg\", else '0'\n"  \
+  "  $<CONFIG_DEBUG>           = '1' if the current config is a debug " \
+  "config (see global property DEBUG_CONFIGURATIONS), 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"    \
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index b8e7f76..784596c 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -288,6 +288,38 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
 } configurationTestNode;
 
 //----------------------------------------------------------------------------
+static const struct DebugTestNode : public cmGeneratorExpressionNode
+{
+  DebugTestNode() {}
+
+  virtual int NumExpectedParameters() const { return 0; }
+
+  std::string Evaluate(const std::vector<std::string> &,
+                       cmGeneratorExpressionContext *context,
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
+  {
+    if (!context->Config)
+      {
+      return "0";
+      }
+
+    std::vector<std::string> const& debugConfigs =
+                    context->Makefile->GetCMakeInstance()->GetDebugConfigs();
+    std::string configUpper = cmSystemTools::UpperCase(context->Config);
+    for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
+        i != debugConfigs.end(); ++i)
+      {
+      if(*i == configUpper)
+        {
+        return "1";
+        }
+      }
+    return "0";
+  }
+} debugTestNode;
+
+//----------------------------------------------------------------------------
 static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 {
   TargetPropertyNode() {}
@@ -590,6 +622,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     return &configurationNode;
   else if (identifier == "CONFIG")
     return &configurationTestNode;
+  else if (identifier == "CONFIG_DEBUG")
+    return &debugTestNode;
   else if (identifier == "TARGET_FILE")
     return &targetFileNode;
   else if (identifier == "TARGET_LINKER_FILE")
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index 66c190a..c2dd55a 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -23,6 +23,7 @@ add_custom_target(check-part1 ALL
     -Dtest_config_release=$<CONFIG:Release>$<CONFIG:RELEASE>$<CONFIG:ReLeAsE>
     -Dtest_config_relwithdebinfo=$<CONFIG:RelWithDebInfo>$<CONFIG:RELWITHDEBINFO>$<CONFIG:relwithdebinfo>
     -Dtest_config_minsizerel=$<CONFIG:MinSizeRel>$<CONFIG:MINSIZEREL>$<CONFIG:minsizerel>
+    -Dtest_config_is_debug=$<CONFIG:Debug>$<CONFIG_DEBUG>
     -Dtest_not_0=$<NOT:0>
     -Dtest_not_1=$<NOT:1>
     -Dtest_or_0=$<OR:0>
diff --git a/Tests/GeneratorExpression/check-part1.cmake b/Tests/GeneratorExpression/check-part1.cmake
index 7abfa82..39f441f 100644
--- a/Tests/GeneratorExpression/check-part1.cmake
+++ b/Tests/GeneratorExpression/check-part1.cmake
@@ -20,6 +20,9 @@ foreach(c debug release relwithdebinfo minsizerel)
     message(SEND_ERROR "test_config_${c} is \"${test_config_${c}}\", not all 0 or all 1")
   endif()
 endforeach()
+if(NOT "${test_config_is_debug}" MATCHES "^(0+|1+)$")
+  message(SEND_ERROR "test_config_is_debug is \"${test_config_is_debug}\", not both 0 or both 1")
+endif()
 check(test_not_0 "1")
 check(test_not_1 "0")
 check(test_or_0 "0")

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=88cf651b76fa8793cd5f78cae03ce4af2958425e
commit 88cf651b76fa8793cd5f78cae03ce4af2958425e
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Sep 23 13:16:44 2012 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Dec 3 08:28:51 2012 -0500

    GenEx: Add expressions to specify build- or install-only values
    
    This is for specifying INCLUDE_DIRECTORIES relevant to the build-location
    or the install location for example:
    
     set_property(TARGET foo PROPERTY
       INTERFACE_INCLUDE_DIRECTORIES
       "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>"
       "$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>"
     )
    
    A 'bar' target can then use:
    
     set_property(TARGET bar PROPERTY
       INCLUDE_DIRECTORIES
       "$<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES>"
     )
    
    and it will work whether foo is in the same project, or an imported target
    from an installation location, or an imported target from a build location
    generated by the export() command.
    
    Because the generator expressions are only evaluated at build-time, these
    new expressions are equivalent to the ZeroNode and OneNode.
    
    Additionally, add the EXPORT_NAMESPACE expression to expand to the
    namespace used when using export() or install(EXPORT).  For example:
    
     set_property(TARGET bar PROPERTY
       INCLUDE_DIRECTORIES
       "$<TARGET_PROPERTY:$<EXPORT_NAMESPACE>foo,INTERFACE_INCLUDE_DIRECTORIES>"
     )
    
    The GeneratorExpression test is split into parts. Some shells can't run
    the custom command as it is getting too long.

diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 445fd0e..2899e05 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -26,6 +26,15 @@
   "strings which contain a '>' for example.\n"                          \
   "  $<COMMA>                  = A literal ','. Used to compare "       \
   "strings which contain a ',' for example.\n"                          \
+  "  $<INSTALL_INTERFACE:...>  = content of \"...\" when the property " \
+  "is exported using install(EXPORT), and empty otherwise.\n"           \
+  "  $<BUILD_INTERFACE:...>    = content of \"...\" when the property " \
+  "is exported using export(), or when the target is used by another "  \
+  "target in the same buildsystem. Expands to the empty string "        \
+  "otherwise.\n"                                                        \
+  "  $<EXPORT_NAMESPACE>       = The namespace used in an invokation "  \
+  "of export() or install(EXPORT). Expands to empty in other "          \
+  "contexts.\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/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 32bf941..2bcced1 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -131,15 +131,9 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
     }
 }
 
-std::string cmGeneratorExpression::Preprocess(const std::string &input,
-                                              PreprocessContext context)
+//----------------------------------------------------------------------------
+static std::string stripAllGeneratorExpressions(const std::string &input)
 {
-  if (context != StripAllGeneratorExpressions)
-  {
-    assert(!"cmGeneratorExpression::Preprocess called with invalid args");
-    return std::string();
-  }
-
   std::string result;
   std::string::size_type pos = 0;
   std::string::size_type lastPos = pos;
@@ -178,3 +172,95 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input,
   result += input.substr(lastPos);
   return result;
 }
+
+//----------------------------------------------------------------------------
+static std::string stripExportInterface(const std::string &input,
+                          cmGeneratorExpression::PreprocessContext context,
+                          const char *ns)
+{
+  std::string result;
+  {
+  std::string::size_type pos = 0;
+  std::string::size_type lastPos = pos;
+  while((pos = input.find("$<BUILD_INTERFACE:", lastPos)) != input.npos
+    || (pos = input.find("$<INSTALL_INTERFACE:", lastPos)) != input.npos)
+    {
+    result += input.substr(lastPos, pos - lastPos);
+    const bool gotInstallInterface = input[pos + 2] == 'I';
+    pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1
+                               : sizeof("$<BUILD_INTERFACE:") - 1;
+    int nestingLevel = 1;
+    const char *c = input.c_str() + pos;
+    const char * const cStart = c;
+    for ( ; *c; ++c)
+      {
+      if(c[0] == '$' && c[1] == '<')
+        {
+        ++nestingLevel;
+        ++c;
+        continue;
+        }
+      if(c[0] == '>')
+        {
+        --nestingLevel;
+        if (nestingLevel != 0)
+          {
+          continue;
+          }
+        if(context == cmGeneratorExpression::BuildInterface
+            && !gotInstallInterface)
+          {
+          result += input.substr(pos, c - cStart);
+          }
+        else if(context == cmGeneratorExpression::InstallInterface
+            && gotInstallInterface)
+          {
+          result += input.substr(pos, c - cStart);
+          }
+        break;
+        }
+      }
+    const std::string::size_type traversed = (c - cStart) + 1;
+    if (!*c)
+      {
+      result += std::string(gotInstallInterface ? "$<INSTALL_INTERFACE:"
+                                                : "$<BUILD_INTERFACE:")
+             + input.substr(pos, traversed);
+      }
+    pos += traversed;
+    lastPos = pos;
+    }
+  result += input.substr(lastPos);
+  }
+
+  {
+  std::string::size_type pos = 0;
+  std::string::size_type lastPos = pos;
+
+  std::string expNs = ns ? ns : "";
+  while((pos = result.find("$<EXPORT_NAMESPACE>", lastPos)) != input.npos)
+    {
+    result.replace(pos, sizeof("$<EXPORT_NAMESPACE>") - 1, expNs);
+    pos += sizeof("$<EXPORT_NAMESPACE>") - 1;
+    }
+  }
+  return result;
+}
+
+//----------------------------------------------------------------------------
+std::string cmGeneratorExpression::Preprocess(const std::string &input,
+                                              PreprocessContext context,
+                                              const char *ns)
+{
+  if (context == StripAllGeneratorExpressions)
+    {
+    return stripAllGeneratorExpressions(input);
+    }
+  else if (context == BuildInterface || context == InstallInterface)
+  {
+    return stripExportInterface(input, context, ns);
+  }
+
+  assert(!"cmGeneratorExpression::Preprocess called with invalid args");
+  return std::string();
+}
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index ea3e7d0..5e3352b 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -48,11 +48,14 @@ public:
   const cmCompiledGeneratorExpression& Parse(const char* input);
 
   enum PreprocessContext {
-    StripAllGeneratorExpressions
+    StripAllGeneratorExpressions,
+    BuildInterface,
+    InstallInterface
   };
 
   static std::string Preprocess(const std::string &input,
-                                PreprocessContext context);
+                                PreprocessContext context,
+                                const char *ns = 0);
 
 private:
   cmGeneratorExpression(const cmGeneratorExpression &);
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 102927e..b8e7f76 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -96,6 +96,31 @@ static const struct OneNode : public cmGeneratorExpressionNode
 } oneNode;
 
 //----------------------------------------------------------------------------
+static const struct OneNode buildInterfaceNode;
+
+//----------------------------------------------------------------------------
+static const struct ZeroNode installInterfaceNode;
+
+//----------------------------------------------------------------------------
+static const struct NullNode : public cmGeneratorExpressionNode
+{
+  NullNode() {}
+
+  virtual bool GeneratesContent() const { return false; }
+
+  std::string Evaluate(const std::vector<std::string> &,
+                       cmGeneratorExpressionContext *,
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
+  {
+    return std::string();
+  }
+
+  virtual int NumExpectedParameters() const { return 0; }
+
+} nullNode;
+
+//----------------------------------------------------------------------------
 #define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
 static const struct OP ## Node : public cmGeneratorExpressionNode \
 { \
@@ -593,6 +618,12 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     return &commaNode;
   else if (identifier == "TARGET_PROPERTY")
     return &targetPropertyNode;
+  else if (identifier == "BUILD_INTERFACE")
+    return &buildInterfaceNode;
+  else if (identifier == "INSTALL_INTERFACE")
+    return &installInterfaceNode;
+  else if (identifier == "EXPORT_NAMESPACE")
+    return &nullNode;
   return 0;
 
 }
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index 3a92d81..66c190a 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -1,7 +1,7 @@
 cmake_minimum_required (VERSION 2.8.8)
 project(GeneratorExpression NONE)
 
-add_custom_target(check ALL
+add_custom_target(check-part1 ALL
   COMMAND ${CMAKE_COMMAND}
     -Dtest_0=$<0:nothing>
     -Dtest_0_with_comma=$<0:-Wl,--no-undefined>
@@ -57,6 +57,13 @@ add_custom_target(check ALL
     -Dtest_colons_3=$<1:Qt5::Core>
     -Dtest_colons_4=$<1:C:\\CMake>
     -Dtest_colons_5=$<1:C:/CMake>
+    -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part1.cmake
+  COMMAND ${CMAKE_COMMAND} -E echo "check done (part 1 of 2)"
+  VERBATIM
+  )
+
+add_custom_target(check-part2 ALL
+  COMMAND ${CMAKE_COMMAND}
     -Dtest_incomplete_1=$<
     -Dtest_incomplete_2=$<something
     -Dtest_incomplete_3=$<something:
@@ -78,7 +85,10 @@ add_custom_target(check ALL
     -Dtest_incomplete_19=$<1:some,thing$<ANGLE-R>
     -Dtest_incomplete_20=$<CONFIGURATION$<ANGLE-R>
     -Dtest_incomplete_21=$<BOOL:something$<ANGLE-R>
-    -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
-  COMMAND ${CMAKE_COMMAND} -E echo "check done"
+    -Dtest_build_interface=$<BUILD_INTERFACE:build>
+    -Dtest_install_interface=$<INSTALL_INTERFACE:install>
+    -Dtest_export_namespace=$<EXPORT_NAMESPACE>x
+    -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake
+  COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)"
   VERBATIM
   )
diff --git a/Tests/GeneratorExpression/check-common.cmake b/Tests/GeneratorExpression/check-common.cmake
new file mode 100644
index 0000000..8ffebd7
--- /dev/null
+++ b/Tests/GeneratorExpression/check-common.cmake
@@ -0,0 +1,5 @@
+macro(check var val)
+  if(NOT "${${var}}" STREQUAL "${val}")
+    message(SEND_ERROR "${var} is \"${${var}}\", not \"${val}\"")
+  endif()
+endmacro()
diff --git a/Tests/GeneratorExpression/check-part1.cmake b/Tests/GeneratorExpression/check-part1.cmake
new file mode 100644
index 0000000..7abfa82
--- /dev/null
+++ b/Tests/GeneratorExpression/check-part1.cmake
@@ -0,0 +1,56 @@
+
+include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake)
+
+message(STATUS "config=[${config}]")
+check(test_0 "")
+check(test_0_with_comma "")
+check(test_1 "content")
+check(test_1_with_comma "-Wl,--no-undefined")
+check(test_and_0 "0")
+check(test_and_0_0 "0")
+check(test_and_0_1 "0")
+check(test_and_1 "1")
+check(test_and_1_0 "0")
+check(test_and_1_1 "1")
+check(test_and_0_invalidcontent "0")
+check(test_config_0 "0")
+check(test_config_1 "1")
+foreach(c debug release relwithdebinfo minsizerel)
+  if(NOT "${test_config_${c}}" MATCHES "^(0+|1+)$")
+    message(SEND_ERROR "test_config_${c} is \"${test_config_${c}}\", not all 0 or all 1")
+  endif()
+endforeach()
+check(test_not_0 "1")
+check(test_not_1 "0")
+check(test_or_0 "0")
+check(test_or_0_0 "0")
+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_or_1_invalidcontent "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_bool_empty "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_strequal_both_empty "1")
+check(test_strequal_one_empty "0")
+check(test_angle_r ">")
+check(test_comma ",")
+check(test_colons_1 ":")
+check(test_colons_2 "::")
+check(test_colons_3 "Qt5::Core")
+check(test_colons_4 "C:\\\\CMake")
+check(test_colons_5 "C:/CMake")
diff --git a/Tests/GeneratorExpression/check-part2.cmake b/Tests/GeneratorExpression/check-part2.cmake
new file mode 100644
index 0000000..4201345
--- /dev/null
+++ b/Tests/GeneratorExpression/check-part2.cmake
@@ -0,0 +1,27 @@
+
+include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake)
+
+check(test_incomplete_1 "$<")
+check(test_incomplete_2 "$<something")
+check(test_incomplete_3 "$<something:")
+check(test_incomplete_4 "$<something:,")
+check(test_incomplete_5 "$something:,>")
+check(test_incomplete_6 "<something:,>")
+check(test_incomplete_7 "$<something::")
+check(test_incomplete_8 "$<something:,")
+check(test_incomplete_9 "$<something:,,")
+check(test_incomplete_10 "$<something:,:")
+check(test_incomplete_11 "$<something,,")
+check(test_incomplete_12 "$<,,")
+check(test_incomplete_13 "$<somespecialthing")
+check(test_incomplete_14 "$<>")
+check(test_incomplete_15 "$<some$<thing")
+check(test_incomplete_16 "$<BOOL:something")
+check(test_incomplete_17 "some$thing")
+check(test_incomplete_18 "$<1:some,thing")
+check(test_incomplete_19 "$<1:some,thing>")
+check(test_incomplete_20 "$<CONFIGURATION>")
+check(test_incomplete_21 "$<BOOL:something>")
+check(test_build_interface "build")
+check(test_install_interface "")
+check(test_export_namespace "x")
diff --git a/Tests/GeneratorExpression/check.cmake b/Tests/GeneratorExpression/check.cmake
deleted file mode 100644
index af436de..0000000
--- a/Tests/GeneratorExpression/check.cmake
+++ /dev/null
@@ -1,80 +0,0 @@
-macro(check var val)
-  if(NOT "${${var}}" STREQUAL "${val}")
-    message(SEND_ERROR "${var} is \"${${var}}\", not \"${val}\"")
-  endif()
-endmacro()
-
-message(STATUS "config=[${config}]")
-check(test_0 "")
-check(test_0_with_comma "")
-check(test_1 "content")
-check(test_1_with_comma "-Wl,--no-undefined")
-check(test_and_0 "0")
-check(test_and_0_0 "0")
-check(test_and_0_1 "0")
-check(test_and_1 "1")
-check(test_and_1_0 "0")
-check(test_and_1_1 "1")
-check(test_and_0_invalidcontent "0")
-check(test_config_0 "0")
-check(test_config_1 "1")
-foreach(c debug release relwithdebinfo minsizerel)
-  if(NOT "${test_config_${c}}" MATCHES "^(0+|1+)$")
-    message(SEND_ERROR "test_config_${c} is \"${test_config_${c}}\", not all 0 or all 1")
-  endif()
-endforeach()
-check(test_not_0 "1")
-check(test_not_1 "0")
-check(test_or_0 "0")
-check(test_or_0_0 "0")
-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_or_1_invalidcontent "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_bool_empty "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_strequal_both_empty "1")
-check(test_strequal_one_empty "0")
-check(test_angle_r ">")
-check(test_comma ",")
-check(test_colons_1 ":")
-check(test_colons_2 "::")
-check(test_colons_3 "Qt5::Core")
-check(test_colons_4 "C:\\\\CMake")
-check(test_colons_5 "C:/CMake")
-check(test_incomplete_1 "$<")
-check(test_incomplete_2 "$<something")
-check(test_incomplete_3 "$<something:")
-check(test_incomplete_4 "$<something:,")
-check(test_incomplete_5 "$something:,>")
-check(test_incomplete_6 "<something:,>")
-check(test_incomplete_7 "$<something::")
-check(test_incomplete_8 "$<something:,")
-check(test_incomplete_9 "$<something:,,")
-check(test_incomplete_10 "$<something:,:")
-check(test_incomplete_11 "$<something,,")
-check(test_incomplete_12 "$<,,")
-check(test_incomplete_13 "$<somespecialthing")
-check(test_incomplete_14 "$<>")
-check(test_incomplete_15 "$<some$<thing")
-check(test_incomplete_16 "$<BOOL:something")
-check(test_incomplete_17 "some$thing")
-check(test_incomplete_18 "$<1:some,thing")
-check(test_incomplete_19 "$<1:some,thing>")
-check(test_incomplete_20 "$<CONFIGURATION>")
-check(test_incomplete_21 "$<BOOL:something>")

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

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list