From d95651e15abbe6dcb771b776dfc69a1412dd0400 Mon Sep 17 00:00:00 2001
From: Stephen Kelly <steveire@gmail.com>
Date: Thu, 6 Jun 2013 18:17:10 +0200
Subject: Overload cmLocalGenerator::AppendDefines to add a list.

---
 Source/cmLocalGenerator.cxx | 6 ++++++
 Source/cmLocalGenerator.h   | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 00846d5..70d7d16 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2301,7 +2301,13 @@ void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
   // Expand the list of definitions.
   std::vector<std::string> defines_vec;
   cmSystemTools::ExpandListArgument(defines_list, defines_vec);
+  this->AppendDefines(defines, defines_vec);
+}
 
+//----------------------------------------------------------------------------
+void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
+                                  const std::vector<std::string> &defines_vec)
+{
   for(std::vector<std::string>::const_iterator di = defines_vec.begin();
       di != defines_vec.end(); ++di)
     {
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index f35ef8e..f5cd7fd 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -166,6 +166,9 @@ public:
   {
     this->AppendDefines(defines, defines_list.c_str());
   }
+  void AppendDefines(std::set<std::string>& defines,
+                     const std::vector<std::string> &defines_vec);
+
   /**
    * Join a set of defines into a definesString with a space separator.
    */
-- 
cgit v0.12


From afc9243c325c37ac7364af12a10adffd7dd81d25 Mon Sep 17 00:00:00 2001
From: Stephen Kelly <steveire@gmail.com>
Date: Wed, 10 Jul 2013 15:22:59 +0200
Subject: Add an overload of cmIDEOptions::AddDefines taking a vector of
 strings.

---
 Source/cmIDEOptions.cxx | 5 +++++
 Source/cmIDEOptions.h   | 1 +
 2 files changed, 6 insertions(+)

diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index 76a60cf..34a9c7c 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -165,6 +165,11 @@ void cmIDEOptions::AddDefines(const char* defines)
     cmSystemTools::ExpandListArgument(defines, this->Defines);
     }
 }
+//----------------------------------------------------------------------------
+void cmIDEOptions::AddDefines(const std::vector<std::string> &defines)
+{
+  this->Defines.insert(this->Defines.end(), defines.begin(), defines.end());
+}
 
 //----------------------------------------------------------------------------
 void cmIDEOptions::AddFlag(const char* flag, const char* value)
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index e556bde..e78af3e 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -27,6 +27,7 @@ public:
   // Store definitions and flags.
   void AddDefine(const std::string& define);
   void AddDefines(const char* defines);
+  void AddDefines(const std::vector<std::string> &defines);
   void AddFlag(const char* flag, const char* value);
   void RemoveFlag(const char* flag);
   const char* GetFlag(const char* flag);
-- 
cgit v0.12


From 184121538c2576b2113c0e256ecb0cd9ac354134 Mon Sep 17 00:00:00 2001
From: Stephen Kelly <steveire@gmail.com>
Date: Thu, 6 Jun 2013 18:13:35 +0200
Subject: Refactor cmTarget::GetCompileDefinitions to use an out-vector, not a
 string.

Refactor to create AddCompileDefinitions.
---
 Source/cmExtraCodeBlocksGenerator.cxx      | 18 +++++++-----------
 Source/cmExtraSublimeTextGenerator.cxx     |  2 +-
 Source/cmGlobalXCodeGenerator.cxx          |  5 +++--
 Source/cmLocalGenerator.cxx                | 11 +++++++++++
 Source/cmLocalGenerator.h                  |  2 ++
 Source/cmLocalUnixMakefileGenerator3.cxx   |  4 ++--
 Source/cmLocalVisualStudio6Generator.cxx   | 20 +++++---------------
 Source/cmLocalVisualStudio7Generator.cxx   |  4 +++-
 Source/cmMakefileTargetGenerator.cxx       |  5 ++---
 Source/cmNinjaTargetGenerator.cxx          |  5 ++---
 Source/cmQtAutomoc.cxx                     | 10 ++++++----
 Source/cmTarget.cxx                        |  8 +++++---
 Source/cmTarget.h                          |  3 ++-
 Source/cmVisualStudio10TargetGenerator.cxx |  5 +++--
 14 files changed, 54 insertions(+), 48 deletions(-)

diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index f6f4cef..dfbb1c0 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -621,19 +621,15 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
                                   ->GetGeneratorTarget(target);
 
     // the compilerdefines for this target
-    std::string cdefs = target->GetCompileDefinitions(buildType);
+    std::vector<std::string> cdefs;
+    target->GetCompileDefinitions(cdefs, buildType);
 
-    if(!cdefs.empty())
+    // Expand the list.
+    for(std::vector<std::string>::const_iterator di = cdefs.begin();
+        di != cdefs.end(); ++di)
       {
-      // Expand the list.
-      std::vector<std::string> defs;
-      cmSystemTools::ExpandListArgument(cdefs.c_str(), defs);
-      for(std::vector<std::string>::const_iterator di = defs.begin();
-          di != defs.end(); ++di)
-        {
-        cmXMLSafe safedef(di->c_str());
-        fout <<"            <Add option=\"-D" << safedef.str() << "\" />\n";
-        }
+      cmXMLSafe safedef(di->c_str());
+      fout <<"            <Add option=\"-D" << safedef.str() << "\" />\n";
       }
 
     // the include directories for this target
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 012013c..d925432 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -463,7 +463,7 @@ ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg, cmTarget *target,
     }
 
   // Add preprocessor definitions for this target and configuration.
-  lg->AppendDefines(defines, target->GetCompileDefinitions(config));
+  lg->AddCompileDefinitions(defines, target, config);
   lg->AppendDefines(defines, source->GetProperty("COMPILE_DEFINITIONS"));
   {
   std::string defPropName = "COMPILE_DEFINITIONS_";
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 9cfbe42..63de1a5 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1741,8 +1741,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
     this->AppendDefines(ppDefs, exportMacro);
     }
   cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
-  this->AppendDefines(ppDefs,
-                      target.GetCompileDefinitions(configName).c_str());
+  std::vector<std::string> targetDefines;
+  target.GetCompileDefinitions(targetDefines, configName);
+  this->AppendDefines(ppDefs, targetDefines);
   buildSettings->AddAttribute
     ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
 
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 70d7d16..6240054 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1339,6 +1339,17 @@ std::string cmLocalGenerator::GetIncludeFlags(
 }
 
 //----------------------------------------------------------------------------
+void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines,
+                                             cmTarget* target,
+                                             const char* config)
+{
+  std::vector<std::string> targetDefines;
+  target->GetCompileDefinitions(targetDefines,
+                               config);
+  this->AppendDefines(defines, targetDefines);
+}
+
+//----------------------------------------------------------------------------
 void cmLocalGenerator::AddCompileOptions(
   std::string& flags, cmTarget* target,
   const char* lang, const char* config
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index f5cd7fd..5c644d1 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -223,6 +223,8 @@ public:
                              bool stripImplicitInclDirs = true);
   void AddCompileOptions(std::string& flags, cmTarget* target,
                          const char* lang, const char* config);
+  void AddCompileDefinitions(std::set<std::string>& defines, cmTarget* target,
+                         const char* config);
 
   /** Compute the language used to compile the given source file.  */
   const char* GetSourceFileLanguage(const cmSourceFile& source);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 78a70f8..1d1acfd 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1962,8 +1962,8 @@ void cmLocalUnixMakefileGenerator3
 
   // Build a list of preprocessor definitions for the target.
   std::set<std::string> defines;
-  this->AppendDefines(defines, target.GetCompileDefinitions(
-                                            this->ConfigurationName.c_str()));
+  this->AddCompileDefinitions(defines, &target,
+                               this->ConfigurationName.c_str());
   if(!defines.empty())
     {
     cmakefileStream
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 0b61e1d..df6e1f1 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -1701,21 +1701,11 @@ void cmLocalVisualStudio6Generator
     std::set<std::string> minsizeDefinesSet;
     std::set<std::string> debugrelDefinesSet;
 
-    this->AppendDefines(
-      definesSet,
-      target.GetCompileDefinitions(0));
-    this->AppendDefines(
-      debugDefinesSet,
-      target.GetCompileDefinitions("DEBUG"));
-    this->AppendDefines(
-      releaseDefinesSet,
-      target.GetCompileDefinitions("RELEASE"));
-    this->AppendDefines(
-      minsizeDefinesSet,
-      target.GetCompileDefinitions("MINSIZEREL"));
-    this->AppendDefines(
-      debugrelDefinesSet,
-      target.GetCompileDefinitions("RELWITHDEBINFO"));
+    this->AddCompileDefinitions(definesSet, &target, 0);
+    this->AddCompileDefinitions(debugDefinesSet, &target, "DEBUG");
+    this->AddCompileDefinitions(releaseDefinesSet, &target, "RELEASE");
+    this->AddCompileDefinitions(minsizeDefinesSet, &target, "MINSIZEREL");
+    this->AddCompileDefinitions(debugrelDefinesSet, &target, "RELWITHDEBINFO");
 
     std::string defines = " ";
     std::string debugDefines = " ";
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 1d2f709..9ecd53d 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -746,7 +746,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
   targetOptions.ParseFinish();
   cmGeneratorTarget* gt =
     this->GlobalGenerator->GetGeneratorTarget(&target);
-  targetOptions.AddDefines(target.GetCompileDefinitions(configName).c_str());
+  std::vector<std::string> targetDefines;
+  target.GetCompileDefinitions(targetDefines, configName);
+  targetOptions.AddDefines(targetDefines);
   targetOptions.SetVerboseMakefile(
     this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
 
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 1492dfa..b19d37d 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -309,9 +309,8 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
       }
 
     // Add preprocessor definitions for this target and configuration.
-    this->LocalGenerator->AppendDefines
-      (defines, this->Target->GetCompileDefinitions(
-                            this->LocalGenerator->ConfigurationName.c_str()));
+    this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
+                            this->LocalGenerator->ConfigurationName.c_str());
 
     std::string definesString;
     this->LocalGenerator->JoinDefines(defines, definesString, lang);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 65173ca..88ab7275 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -201,9 +201,8 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
     }
 
   // Add preprocessor definitions for this target and configuration.
-  this->LocalGenerator->AppendDefines
-    (defines,
-     this->Target->GetCompileDefinitions(this->GetConfigName()));
+  this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
+                                             this->GetConfigName());
   this->LocalGenerator->AppendDefines
     (defines,
      source->GetProperty("COMPILE_DEFINITIONS"));
diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx
index 34b3c7e..93e39ab 100644
--- a/Source/cmQtAutomoc.cxx
+++ b/Source/cmQtAutomoc.cxx
@@ -175,15 +175,17 @@ static void GetCompileDefinitionsAndDirectories(cmTarget *target,
     incs += *incDirIt;
     }
 
-  defs = target->GetCompileDefinitions(config);
+  std::set<std::string> defines;
+  localGen->AddCompileDefinitions(defines, target, config);
 
-  const char *tmp = makefile->GetProperty("COMPILE_DEFINITIONS");
   sep = "";
-  if (tmp)
+  for(std::set<std::string>::const_iterator defIt = defines.begin();
+      defIt != defines.end();
+      ++defIt)
     {
     defs += sep;
     sep = ";";
-    defs += tmp;
+    defs += *defIt;
     }
 }
 
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index a90fa74..02dcf81 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -3384,7 +3384,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
 }
 
 //----------------------------------------------------------------------------
-std::string cmTarget::GetCompileDefinitions(const char *config)
+void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
+                                            const char *config)
 {
   const char *configProp = 0;
   if (config)
@@ -3419,7 +3420,8 @@ std::string cmTarget::GetCompileDefinitions(const char *config)
 
   if (libs.empty())
     {
-    return result;
+    cmSystemTools::ExpandListArgument(result, list);
+    return;
     }
 
   std::string sep;
@@ -3467,7 +3469,7 @@ std::string cmTarget::GetCompileDefinitions(const char *config)
                                                                       = true;
     }
 
-  return result;
+  cmSystemTools::ExpandListArgument(result, list);
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 3bc0ab2..ab3dff2 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -442,7 +442,8 @@ public:
       If no macro should be defined null is returned.  */
   const char* GetExportMacro();
 
-  std::string GetCompileDefinitions(const char *config);
+  void GetCompileDefinitions(std::vector<std::string> &result,
+                             const char *config);
 
   // Compute the set of languages compiled by the target.  This is
   // computed every time it is called because the languages can change
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 50f195e..d59de11 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1337,8 +1337,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
   clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
   clOptions.Parse(flags.c_str());
   clOptions.Parse(defineFlags.c_str());
-  clOptions.AddDefines(this->Target->GetCompileDefinitions(
-                                                configName.c_str()).c_str());
+  std::vector<std::string> targetDefines;
+  this->Target->GetCompileDefinitions(targetDefines, configName.c_str());
+  clOptions.AddDefines(targetDefines);
   clOptions.SetVerboseMakefile(
     this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
 
-- 
cgit v0.12


From d7dd01083a99055d689c80fe28bbc79a11bf3da1 Mon Sep 17 00:00:00 2001
From: Stephen Kelly <steveire@gmail.com>
Date: Wed, 12 Jun 2013 10:12:51 +0200
Subject: Add target property debugging for COMPILE_DEFINITIONS

Use constructs similar to those for COMPILE_OPTIONS. This is a little
different because there is a command to remove_definitions(), so
we can't populate the equivalent target property until generate-time
in cmGlobalGenerator.
---
 Source/cmGlobalGenerator.cxx |  13 ++-
 Source/cmMakefile.cxx        |  41 ++++++++
 Source/cmMakefile.h          |   5 +
 Source/cmTarget.cxx          | 232 +++++++++++++++++++++++++++++++------------
 Source/cmTarget.h            |   3 +
 5 files changed, 228 insertions(+), 66 deletions(-)

diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index ad74767..0022605 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1121,8 +1121,9 @@ void cmGlobalGenerator::CreateGeneratorTargets()
     cmGeneratorTargetsType generatorTargets;
 
     cmMakefile *mf = this->LocalGenerators[i]->GetMakefile();
-    const char *noconfig_compile_definitions =
-                                      mf->GetProperty("COMPILE_DEFINITIONS");
+
+    const std::vector<cmValueWithOrigin> noconfig_compile_definitions =
+                                mf->GetCompileDefinitionsEntries();
 
     std::vector<std::string> configs;
     mf->GetConfigurations(configs);
@@ -1134,7 +1135,13 @@ void cmGlobalGenerator::CreateGeneratorTargets()
       cmTarget* t = &ti->second;
 
       {
-      t->AppendProperty("COMPILE_DEFINITIONS", noconfig_compile_definitions);
+      for (std::vector<cmValueWithOrigin>::const_iterator it
+                                      = noconfig_compile_definitions.begin();
+          it != noconfig_compile_definitions.end(); ++it)
+        {
+        t->InsertCompileDefinition(*it);
+        }
+
       for(std::vector<std::string>::const_iterator ci = configs.begin();
           ci != configs.end(); ++ci)
         {
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index f3a66ba..d94c93d 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1505,6 +1505,12 @@ void cmMakefile::InitializeFromParent()
                                      parentOptions.begin(),
                                      parentOptions.end());
 
+  const std::vector<cmValueWithOrigin> parentDefines =
+                                      parent->GetCompileDefinitionsEntries();
+  this->CompileDefinitionsEntries.insert(this->CompileDefinitionsEntries.end(),
+                                     parentDefines.begin(),
+                                     parentDefines.end());
+
   this->SystemIncludeDirectories = parent->SystemIncludeDirectories;
 
   // define flags
@@ -3493,6 +3499,19 @@ void cmMakefile::SetProperty(const char* prop, const char* value)
     this->CompileOptionsEntries.push_back(cmValueWithOrigin(value, lfbt));
     return;
     }
+  if (propname == "COMPILE_DEFINITIONS")
+    {
+    this->CompileDefinitionsEntries.clear();
+    if (!value)
+      {
+      return;
+      }
+    cmListFileBacktrace lfbt;
+    this->GetBacktrace(lfbt);
+    cmValueWithOrigin entry(value, lfbt);
+    this->CompileDefinitionsEntries.push_back(entry);
+    return;
+    }
 
   if ( propname == "INCLUDE_REGULAR_EXPRESSION" )
     {
@@ -3540,6 +3559,14 @@ void cmMakefile::AppendProperty(const char* prop, const char* value,
                                         cmValueWithOrigin(value, lfbt));
     return;
     }
+  if (propname == "COMPILE_DEFINITIONS")
+    {
+    cmListFileBacktrace lfbt;
+    this->GetBacktrace(lfbt);
+    this->CompileDefinitionsEntries.push_back(
+                                        cmValueWithOrigin(value, lfbt));
+    return;
+    }
   if ( propname == "LINK_DIRECTORIES" )
     {
     std::vector<std::string> varArgsExpanded;
@@ -3679,6 +3706,20 @@ const char *cmMakefile::GetProperty(const char* prop,
       }
     return output.c_str();
     }
+  else if (!strcmp("COMPILE_DEFINITIONS",prop))
+    {
+    std::string sep;
+    for (std::vector<cmValueWithOrigin>::const_iterator
+        it = this->CompileDefinitionsEntries.begin(),
+        end = this->CompileDefinitionsEntries.end();
+        it != end; ++it)
+      {
+      output += sep;
+      output += it->Value;
+      sep = ";";
+      }
+    return output.c_str();
+    }
 
   bool chain = false;
   const char *retVal =
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 4297155..1b10773 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -871,6 +871,10 @@ public:
   {
     return this->CompileOptionsEntries;
   }
+  std::vector<cmValueWithOrigin> GetCompileDefinitionsEntries() const
+  {
+    return this->CompileDefinitionsEntries;
+  }
 
   bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; }
   void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; }
@@ -925,6 +929,7 @@ protected:
 
   std::vector<cmValueWithOrigin> IncludeDirectoriesEntries;
   std::vector<cmValueWithOrigin> CompileOptionsEntries;
+  std::vector<cmValueWithOrigin> CompileDefinitionsEntries;
 
   // Track the value of the computed DEFINITIONS property.
   void AddDefineFlag(const char*, std::string&);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 02dcf81..a56eb9e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -141,13 +141,15 @@ public:
   };
   std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
   std::vector<TargetPropertyEntry*> CompileOptionsEntries;
+  std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
   std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
 
   std::map<std::string, std::vector<TargetPropertyEntry*> >
                                 CachedLinkInterfaceIncludeDirectoriesEntries;
   std::map<std::string, std::vector<TargetPropertyEntry*> >
                                 CachedLinkInterfaceCompileOptionsEntries;
-  std::map<std::string, std::string> CachedLinkInterfaceCompileDefinitions;
+  std::map<std::string, std::vector<TargetPropertyEntry*> >
+                                CachedLinkInterfaceCompileDefinitionsEntries;
 
   std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
   std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
@@ -186,6 +188,7 @@ cmTargetInternals::~cmTargetInternals()
 {
   deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
   deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
+  deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
 }
 
 //----------------------------------------------------------------------------
@@ -205,6 +208,7 @@ cmTarget::cmTarget()
   this->BuildInterfaceIncludesAppended = false;
   this->DebugIncludesDone = false;
   this->DebugCompileOptionsDone = false;
+  this->DebugCompileDefinitionsDone = false;
 }
 
 //----------------------------------------------------------------------------
@@ -2845,6 +2849,17 @@ void cmTarget::SetProperty(const char* prop, const char* value)
                           new cmTargetInternals::TargetPropertyEntry(cge));
     return;
     }
+  if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
+    {
+    cmListFileBacktrace lfbt;
+    this->Makefile->GetBacktrace(lfbt);
+    cmGeneratorExpression ge(lfbt);
+    deleteAndClear(this->Internal->CompileDefinitionsEntries);
+    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+    this->Internal->CompileDefinitionsEntries.push_back(
+                          new cmTargetInternals::TargetPropertyEntry(cge));
+    return;
+    }
   if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
     {
     cmOStringStream e;
@@ -2896,6 +2911,15 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
               new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
     return;
     }
+  if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
+    {
+    cmListFileBacktrace lfbt;
+    this->Makefile->GetBacktrace(lfbt);
+    cmGeneratorExpression ge(lfbt);
+    this->Internal->CompileDefinitionsEntries.push_back(
+              new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
+    return;
+    }
   if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
     {
     cmOStringStream e;
@@ -3000,6 +3024,20 @@ void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry,
 }
 
 //----------------------------------------------------------------------------
+void cmTarget::InsertCompileDefinition(const cmValueWithOrigin &entry,
+                     bool before)
+{
+  cmGeneratorExpression ge(entry.Backtrace);
+
+  std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
+                = before ? this->Internal->CompileDefinitionsEntries.begin()
+                         : this->Internal->CompileDefinitionsEntries.end();
+
+  this->Internal->CompileDefinitionsEntries.insert(position,
+      new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
+}
+
+//----------------------------------------------------------------------------
 static void processIncludeDirectories(cmTarget *tgt,
       const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
       std::vector<std::string> &includes,
@@ -3231,12 +3269,12 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
 }
 
 //----------------------------------------------------------------------------
-static void processCompileOptions(cmTarget *tgt,
+static void processCompileOptionsInternal(cmTarget *tgt,
       const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
       std::vector<std::string> &options,
       std::set<std::string> &uniqueOptions,
       cmGeneratorExpressionDAGChecker *dagChecker,
-      const char *config, bool debugOptions)
+      const char *config, bool debugOptions, const char *logName)
 {
   cmMakefile *mf = tgt->GetMakefile();
 
@@ -3281,7 +3319,8 @@ static void processCompileOptions(cmTarget *tgt,
     if (!usedOptions.empty())
       {
       mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
-                            std::string("Used compile options for target ")
+                            std::string("Used compile ") + logName
+                            + std::string(" for target ")
                             + tgt->GetName() + ":\n"
                             + usedOptions, (*it)->ge->GetBacktrace());
       }
@@ -3289,6 +3328,18 @@ static void processCompileOptions(cmTarget *tgt,
 }
 
 //----------------------------------------------------------------------------
+static void processCompileOptions(cmTarget *tgt,
+      const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+      std::vector<std::string> &options,
+      std::set<std::string> &uniqueOptions,
+      cmGeneratorExpressionDAGChecker *dagChecker,
+      const char *config, bool debugOptions)
+{
+  processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+                                dagChecker, config, debugOptions, "options");
+}
+
+//----------------------------------------------------------------------------
 void cmTarget::GetCompileOptions(std::vector<std::string> &result,
                                  const char *config)
 {
@@ -3384,92 +3435,128 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
 }
 
 //----------------------------------------------------------------------------
+static void processCompileDefinitions(cmTarget *tgt,
+      const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+      std::vector<std::string> &options,
+      std::set<std::string> &uniqueOptions,
+      cmGeneratorExpressionDAGChecker *dagChecker,
+      const char *config, bool debugOptions)
+{
+  processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+                                dagChecker, config, debugOptions,
+                                "definitions");
+}
+
+//----------------------------------------------------------------------------
 void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
                                             const char *config)
 {
-  const char *configProp = 0;
-  if (config)
-    {
-    std::string configPropName;
-    configPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
-    configProp = this->GetProperty(configPropName.c_str());
-    }
-
-  const char *noconfigProp = this->GetProperty("COMPILE_DEFINITIONS");
+  std::set<std::string> uniqueOptions;
   cmListFileBacktrace lfbt;
+
   cmGeneratorExpressionDAGChecker dagChecker(lfbt,
-                                            this->GetName(),
-                                            "COMPILE_DEFINITIONS", 0, 0);
+                                              this->GetName(),
+                                              "COMPILE_DEFINITIONS", 0, 0);
 
-  std::string defsString = (noconfigProp ? noconfigProp : "");
-  if (configProp && noconfigProp)
+  std::vector<std::string> debugProperties;
+  const char *debugProp =
+              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+  if (debugProp)
     {
-    defsString += ";";
+    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
     }
-  defsString += (configProp ? configProp : "");
-
-  cmGeneratorExpression ge(lfbt);
-  std::string result = ge.Parse(defsString.c_str())->Evaluate(this->Makefile,
-                                config,
-                                false,
-                                this,
-                                &dagChecker);
 
-  std::vector<std::string> libs;
-  this->GetDirectLinkLibraries(config, libs, this);
+  bool debugDefines = !this->DebugCompileDefinitionsDone
+                          && std::find(debugProperties.begin(),
+                                debugProperties.end(),
+                                "COMPILE_DEFINITIONS")
+                        != debugProperties.end();
 
-  if (libs.empty())
+  if (this->Makefile->IsGeneratingBuildSystem())
     {
-    cmSystemTools::ExpandListArgument(result, list);
-    return;
+    this->DebugCompileDefinitionsDone = true;
     }
 
-  std::string sep;
-  std::string depString;
-  for (std::vector<std::string>::const_iterator it = libs.begin();
-      it != libs.end(); ++it)
-    {
-    if ((cmGeneratorExpression::IsValidTargetName(it->c_str())
-          || cmGeneratorExpression::Find(it->c_str()) != std::string::npos)
-        && this->Makefile->FindTargetToUse(it->c_str()))
-      {
-      depString += sep + "$<TARGET_PROPERTY:"
-                + *it + ",INTERFACE_COMPILE_DEFINITIONS>";
-      sep = ";";
-      }
-    }
+  processCompileDefinitions(this,
+                            this->Internal->CompileDefinitionsEntries,
+                            list,
+                            uniqueOptions,
+                            &dagChecker,
+                            config,
+                            debugDefines);
 
   std::string configString = config ? config : "";
   if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString])
     {
-    cmGeneratorExpression ge2(lfbt);
-    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge2 =
-                                                        ge2.Parse(depString);
-    this->Internal->CachedLinkInterfaceCompileDefinitions[configString] =
-                                                cge2->Evaluate(this->Makefile,
-                                                               config,
-                                                               false,
-                                                               this,
-                                                               &dagChecker);
-    }
-  if (!this->Internal->CachedLinkInterfaceCompileDefinitions[configString]
-                                                                    .empty())
-    {
-    result += (result.empty() ? "" : ";")
-        + this->Internal->CachedLinkInterfaceCompileDefinitions[configString];
+    for (std::vector<cmValueWithOrigin>::const_iterator
+        it = this->Internal->LinkInterfacePropertyEntries.begin(),
+        end = this->Internal->LinkInterfacePropertyEntries.end();
+        it != end; ++it)
+      {
+      {
+      cmGeneratorExpression ge(lfbt);
+      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+                                                        ge.Parse(it->Value);
+      std::string targetResult = cge->Evaluate(this->Makefile, config,
+                                        false, this, 0, 0);
+      if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
+        {
+        continue;
+        }
+      }
+      std::string defsGenex = "$<TARGET_PROPERTY:" +
+                              it->Value + ",INTERFACE_COMPILE_DEFINITIONS>";
+      if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
+        {
+        // Because it->Value is a generator expression, ensure that it
+        // evaluates to the non-empty string before being used in the
+        // TARGET_PROPERTY expression.
+        defsGenex = "$<$<BOOL:" + it->Value + ">:" + defsGenex + ">";
+        }
+      cmGeneratorExpression ge(it->Backtrace);
+      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
+                                                                defsGenex);
+
+      this->Internal
+        ->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back(
+                        new cmTargetInternals::TargetPropertyEntry(cge,
+                                                              it->Value));
+      }
+    if (config)
+      {
+      std::string configPropName = "COMPILE_DEFINITIONS_"
+                                          + cmSystemTools::UpperCase(config);
+      const char *configProp = this->GetProperty(configPropName.c_str());
+      std::string defsString = (configProp ? configProp : "");
+
+      cmGeneratorExpression ge(lfbt);
+      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+                                                        ge.Parse(defsString);
+      this->Internal
+        ->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back(
+                        new cmTargetInternals::TargetPropertyEntry(cge));
+      }
+
     }
 
+  processCompileDefinitions(this,
+    this->Internal->CachedLinkInterfaceCompileDefinitionsEntries[configString],
+                            list,
+                            uniqueOptions,
+                            &dagChecker,
+                            config,
+                            debugDefines);
+
   if (!this->Makefile->IsGeneratingBuildSystem())
     {
-    this->Internal->CachedLinkInterfaceCompileDefinitions[configString] = "";
+    deleteAndClear(this->Internal
+                              ->CachedLinkInterfaceCompileDefinitionsEntries);
     }
   else
     {
     this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString]
                                                                       = true;
     }
-
-  cmSystemTools::ExpandListArgument(result, list);
 }
 
 //----------------------------------------------------------------------------
@@ -3841,6 +3928,24 @@ const char *cmTarget::GetProperty(const char* prop,
       }
     return output.c_str();
     }
+  if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
+    {
+    static std::string output;
+    output = "";
+    std::string sep;
+    typedef cmTargetInternals::TargetPropertyEntry
+                                TargetPropertyEntry;
+    for (std::vector<TargetPropertyEntry*>::const_iterator
+        it = this->Internal->CompileDefinitionsEntries.begin(),
+        end = this->Internal->CompileDefinitionsEntries.end();
+        it != end; ++it)
+      {
+      output += sep;
+      output += (*it)->ge->GetInput();
+      sep = ";";
+      }
+    return output.c_str();
+    }
 
   if (strcmp(prop,"IMPORTED") == 0)
     {
@@ -6566,6 +6671,7 @@ cmTargetInternalPointer::~cmTargetInternalPointer()
 {
   deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
   deleteAndClear(this->Pointer->CompileOptionsEntries);
+  deleteAndClear(this->Pointer->CompileDefinitionsEntries);
   delete this->Pointer;
 }
 
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index ab3dff2..adaae47 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -514,6 +514,8 @@ public:
                      bool before = false);
   void InsertCompileOption(const cmValueWithOrigin &entry,
                      bool before = false);
+  void InsertCompileDefinition(const cmValueWithOrigin &entry,
+                     bool before = false);
 
   void AppendBuildInterfaceIncludes();
 
@@ -650,6 +652,7 @@ private:
   bool IsImportedTarget;
   bool DebugIncludesDone;
   bool DebugCompileOptionsDone;
+  bool DebugCompileDefinitionsDone;
   mutable std::set<std::string> LinkImplicitNullProperties;
   bool BuildInterfaceIncludesAppended;
 
-- 
cgit v0.12