[Cmake-commits] CMake branch, next, updated. v2.8.11-2397-g005bee3

Stephen Kelly steveire at gmail.com
Sun Jun 2 05:57:10 EDT 2013


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  005bee38730724b52405da0957a92063acc0ea14 (commit)
       via  24466f22c0c0e3235f0a21bd2a298c39df50e2f3 (commit)
       via  80ca9c4b41ecdce069a6c3f4c1b558084a748876 (commit)
       via  7cb23084b2595d06aea46cead0e077b5f13aeddb (commit)
       via  47f80d9c43eaa31c32b33a977bdbeda319671dd6 (commit)
       via  1319a147bdc15f4a5a6a8dc56f0198600ff04c42 (commit)
       via  35496761a58956bd8c5ad65a3ed9ee78d09af56b (commit)
       via  f3ad863ae6f0487bbf80d95b0d3f622840187a6a (commit)
       via  a4d8c64d10105fd4448ffde6a5d2fb74c1bb4f57 (commit)
       via  86f5460398ed5fa024aed6cbe0d5862f76a14439 (commit)
      from  1e3d974e792b2afac1b2f3fb89f59e8631d33834 (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=005bee38730724b52405da0957a92063acc0ea14
commit 005bee38730724b52405da0957a92063acc0ea14
Merge: 1e3d974 24466f2
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Jun 2 05:57:07 2013 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Sun Jun 2 05:57:07 2013 -0400

    Merge topic 'target-COMPILE_OPTIONS' into next
    
    24466f2 Add target_compile_options command.
    80ca9c4 Add COMPILE_OPTIONS target property.
    7cb2308 cmTarget: Rename LinkInterfaceIncludeDirectoriesEntries
    47f80d9 cmTarget: Rename struct to be more re-usable.
    1319a14 Add <LANG>_COMPILER_ID generator expressions.
    3549676 Add cmLocalGenerator::GetCompileOptions.
    f3ad863 VS6: Rename some variables to correspond to config values.
    a4d8c64 CMake Nightly Date Stamp
    86f5460 CMake Nightly Date Stamp


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=24466f22c0c0e3235f0a21bd2a298c39df50e2f3
commit 24466f22c0c0e3235f0a21bd2a298c39df50e2f3
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu May 16 15:20:16 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Sun Jun 2 11:56:37 2013 +0200

    Add target_compile_options command.
    
    This command populates the COMPILE_OPTIONS target property.

diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 227b226..75f2ae8 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -29,6 +29,7 @@
 #include "cmSourceGroupCommand.cxx"
 #include "cmSubdirDependsCommand.cxx"
 #include "cmTargetCompileDefinitionsCommand.cxx"
+#include "cmTargetCompileOptionsCommand.cxx"
 #include "cmTargetIncludeDirectoriesCommand.cxx"
 #include "cmTargetPropCommandBase.cxx"
 #include "cmUseMangledMesaCommand.cxx"
@@ -71,6 +72,7 @@ void GetPredefinedCommands(std::list<cmCommand*>&
   commands.push_back(new cmSubdirDependsCommand);
   commands.push_back(new cmTargetIncludeDirectoriesCommand);
   commands.push_back(new cmTargetCompileDefinitionsCommand);
+  commands.push_back(new cmTargetCompileOptionsCommand);
   commands.push_back(new cmUseMangledMesaCommand);
   commands.push_back(new cmUtilitySourceCommand);
   commands.push_back(new cmVariableRequiresCommand);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index ea5552e..1f20be2 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -2915,6 +2915,20 @@ void cmTarget::InsertInclude(const cmValueWithOrigin &entry,
 }
 
 //----------------------------------------------------------------------------
+void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry,
+                     bool before)
+{
+  cmGeneratorExpression ge(entry.Backtrace);
+
+  std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
+                = before ? this->Internal->CompileOptionsEntries.begin()
+                         : this->Internal->CompileOptionsEntries.end();
+
+  this->Internal->CompileOptionsEntries.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,
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 7ec10df..b3d1131 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -500,6 +500,8 @@ public:
   std::vector<std::string> GetIncludeDirectories(const char *config);
   void InsertInclude(const cmValueWithOrigin &entry,
                      bool before = false);
+  void InsertCompileOption(const cmValueWithOrigin &entry,
+                     bool before = false);
 
   void AppendBuildInterfaceIncludes();
 
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
new file mode 100644
index 0000000..e80c845
--- /dev/null
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -0,0 +1,62 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <steveire at gmail.com>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmTargetCompileOptionsCommand.h"
+
+bool cmTargetCompileOptionsCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+  return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE);
+}
+
+void cmTargetCompileOptionsCommand
+::HandleImportedTarget(const std::string &tgt)
+{
+  cmOStringStream e;
+  e << "Cannot specify compile options for imported target \""
+    << tgt << "\".";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+void cmTargetCompileOptionsCommand
+::HandleMissingTarget(const std::string &name)
+{
+  cmOStringStream e;
+  e << "Cannot specify compile options for target \"" << name << "\" "
+       "which is not built by this project.";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+std::string cmTargetCompileOptionsCommand
+::Join(const std::vector<std::string> &content)
+{
+  std::string defs;
+  std::string sep;
+  for(std::vector<std::string>::const_iterator it = content.begin();
+    it != content.end(); ++it)
+    {
+    defs += sep + *it;
+    sep = ";";
+    }
+  return defs;
+}
+
+//----------------------------------------------------------------------------
+void cmTargetCompileOptionsCommand
+::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
+                                   bool)
+{
+  cmListFileBacktrace lfbt;
+  this->Makefile->GetBacktrace(lfbt);
+  cmValueWithOrigin entry(this->Join(content), lfbt);
+  tgt->InsertCompileOption(entry);
+}
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
new file mode 100644
index 0000000..87fa1a7
--- /dev/null
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -0,0 +1,90 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <steveire at gmail.com>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
+#ifndef cmTargetCompileOptionsCommand_h
+#define cmTargetCompileOptionsCommand_h
+
+#include "cmTargetPropCommandBase.h"
+
+class cmTargetCompileOptionsCommand : public cmTargetPropCommandBase
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone()
+    {
+    return new cmTargetCompileOptionsCommand;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const& args,
+                           cmExecutionStatus &status);
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() const { return "target_compile_options";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() const
+    {
+    return
+      "Add compile options to a target.";
+    }
+
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation() const
+    {
+    return
+      "  target_compile_options(<target> [BEFORE] "
+      "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
+      "    [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
+      "Specify compile options to use when compiling a given target.  "
+      "The named <target> must have been created by a command such as "
+      "add_executable or add_library and must not be an IMPORTED target.  "
+      "If BEFORE is specified, the content will be prepended to the property "
+      "instead of being appended.\n"
+      "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
+      "the scope of the following arguments.  PRIVATE and PUBLIC items will "
+      "populate the COMPILE_OPTIONS property of <target>.  PUBLIC and "
+      "INTERFACE items will populate the INTERFACE_COMPILE_OPTIONS "
+      "property of <target>.   "
+      "The following arguments specify compile opitions.  "
+      "Repeated calls for the same <target> append items in the order called."
+      "\n"
+      "Arguments to target_compile_options may use \"generator "
+      "expressions\" with the syntax \"$<...>\".  "
+      CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+      ;
+    }
+
+  cmTypeMacro(cmTargetCompileOptionsCommand, cmTargetPropCommandBase);
+
+private:
+  virtual void HandleImportedTarget(const std::string &tgt);
+  virtual void HandleMissingTarget(const std::string &name);
+
+  virtual void HandleDirectContent(cmTarget *tgt,
+                                   const std::vector<std::string> &content,
+                                   bool prepend);
+  virtual std::string Join(const std::vector<std::string> &content);
+};
+
+#endif
diff --git a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
new file mode 100644
index 0000000..06a48fb
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
@@ -0,0 +1,35 @@
+
+cmake_minimum_required(VERSION 2.8)
+
+project(target_compile_options)
+
+add_executable(target_compile_options
+  "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
+)
+target_compile_options(target_compile_options
+  PRIVATE $<$<CXX_COMPILER_ID:GNU>:-DMY_PRIVATE_DEFINE>
+  PUBLIC $<$<CXX_COMPILER_ID:GNU>:-DMY_PUBLIC_DEFINE>
+  INTERFACE $<$<CXX_COMPILER_ID:GNU>:-DMY_INTERFACE_DEFINE>
+)
+
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+  target_compile_definitions(target_compile_options
+    PRIVATE
+      "DO_GNU_TESTS"
+  )
+endif()
+
+add_executable(consumer
+  "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
+)
+
+target_compile_options(consumer
+  PRIVATE $<$<CXX_COMPILER_ID:GNU>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>>
+)
+
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+  target_compile_definitions(consumer
+    PRIVATE
+      "DO_GNU_TESTS"
+  )
+endif()
diff --git a/Tests/CMakeCommands/target_compile_options/consumer.cpp b/Tests/CMakeCommands/target_compile_options/consumer.cpp
new file mode 100644
index 0000000..1299606
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_options/consumer.cpp
@@ -0,0 +1,18 @@
+
+#ifdef DO_GNU_TESTS
+
+#  ifdef MY_PRIVATE_DEFINE
+#  error Unexpected MY_PRIVATE_DEFINE
+#  endif
+
+#  ifndef MY_PUBLIC_DEFINE
+#  error Expected MY_PUBLIC_DEFINE
+#  endif
+
+#  ifndef MY_INTERFACE_DEFINE
+#  error Expected MY_INTERFACE_DEFINE
+#  endif
+
+#endif
+
+int main() { return 0; }
diff --git a/Tests/CMakeCommands/target_compile_options/main.cpp b/Tests/CMakeCommands/target_compile_options/main.cpp
new file mode 100644
index 0000000..961c06d
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_options/main.cpp
@@ -0,0 +1,18 @@
+
+#ifdef DO_GNU_TESTS
+
+#  ifndef MY_PRIVATE_DEFINE
+#  error Expected MY_PRIVATE_DEFINE
+#  endif
+
+#  ifndef MY_PUBLIC_DEFINE
+#  error Expected MY_PUBLIC_DEFINE
+#  endif
+
+#  ifdef MY_INTERFACE_DEFINE
+#  error Unexpected MY_INTERFACE_DEFINE
+#  endif
+
+#endif
+
+int main() { return 0; }
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 3a28be2..e16fd01 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1967,6 +1967,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
   ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries)
   ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories)
   ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions)
+  ADD_TEST_MACRO(CMakeCommands.target_compile_options target_compile_options)
 
   configure_file(
     "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in"

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=80ca9c4b41ecdce069a6c3f4c1b558084a748876
commit 80ca9c4b41ecdce069a6c3f4c1b558084a748876
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu May 16 15:15:28 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Sun Jun 2 11:56:37 2013 +0200

    Add COMPILE_OPTIONS target property.
    
    This method reads generator expressions from the COMPILE_OPTIONS
    target property, as well as INTERFACE_COMPILE_OPTIONS from linked
    dependents.

diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 5cb50b9..e5ffb0c 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -168,3 +168,11 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const
        || strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0
        || strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0);
 }
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::EvaluatingCompileOptions() const
+{
+  const char *prop = this->Property.c_str();
+  return (strcmp(prop, "COMPILE_OPTIONS") == 0
+       || strcmp(prop, "INTERFACE_COMPILE_OPTIONS") == 0 );
+}
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 62a5cdf..8d9fd76 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -40,6 +40,7 @@ struct cmGeneratorExpressionDAGChecker
   bool EvaluatingLinkLibraries();
   bool EvaluatingIncludeDirectories() const;
   bool EvaluatingCompileDefinitions() const;
+  bool EvaluatingCompileOptions() const;
 
 private:
   Result checkGraph() const;
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index f27761a..5e7d00d 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -495,6 +495,7 @@ static const struct JoinNode : public cmGeneratorExpressionNode
 static const char* targetPropertyTransitiveWhitelist[] = {
     "INTERFACE_INCLUDE_DIRECTORIES"
   , "INTERFACE_COMPILE_DEFINITIONS"
+  , "INTERFACE_COMPILE_OPTIONS"
 };
 
 std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
@@ -702,7 +703,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
       else
         {
         assert(dagCheckerParent->EvaluatingIncludeDirectories()
-            || dagCheckerParent->EvaluatingCompileDefinitions());
+            || dagCheckerParent->EvaluatingCompileDefinitions()
+            || dagCheckerParent->EvaluatingCompileOptions());
         }
       }
 
@@ -721,6 +723,11 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
       {
       interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
       }
+    else if (propertyName == "INTERFACE_COMPILE_OPTIONS"
+        || propertyName == "COMPILE_OPTIONS")
+      {
+      interfacePropertyName = "INTERFACE_COMPILE_OPTIONS";
+      }
 
     const char **transBegin = targetPropertyTransitiveWhitelist;
     const char **transEnd = targetPropertyTransitiveWhitelist
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 9429450..57e25a1 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1334,6 +1334,14 @@ void cmLocalGenerator::GetCompileOptions(std::string& flags,
     {
     this->AppendFlags(flags, prop);
     }
+
+  std::vector<std::string> opts; // TODO: Emitted.
+  target->GetCompileOptions(opts, config);
+  for(std::vector<std::string>::const_iterator li = opts.begin();
+      li != opts.end(); ++li)
+    {
+    this->AppendFlags(flags, li->c_str());
+    }
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index a54f80b..ea5552e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -140,14 +140,18 @@ public:
     const std::string TargetName;
   };
   std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
+  std::vector<TargetPropertyEntry*> CompileOptionsEntries;
   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, bool> CacheLinkInterfaceIncludeDirectoriesDone;
   std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
+  std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
 };
 
 //----------------------------------------------------------------------------
@@ -181,6 +185,7 @@ void deleteAndClear(
 cmTargetInternals::~cmTargetInternals()
 {
   deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
+  deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
 }
 
 //----------------------------------------------------------------------------
@@ -199,6 +204,7 @@ cmTarget::cmTarget()
   this->IsImportedTarget = false;
   this->BuildInterfaceIncludesAppended = false;
   this->DebugIncludesDone = false;
+  this->DebugCompileOptionsDone = false;
 }
 
 //----------------------------------------------------------------------------
@@ -287,6 +293,32 @@ void cmTarget::DefineProperties(cmake *cm)
      "This is the configuration-specific version of COMPILE_DEFINITIONS.");
 
   cm->DefineProperty
+    ("COMPILE_OPTIONS", cmProperty::TARGET,
+     "List of options to pass to the compiler.",
+     "This property specifies the list of options specified "
+     "so far for this property.  "
+     "This property exists on targets only.  "
+     "\n"
+     "The target property values are used by the generators to set "
+     "the options for the compiler.\n"
+     "Contents of COMPILE_OPTIONS may use \"generator expressions\" with "
+     "the syntax \"$<...>\".  "
+     CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+     CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
+
+  cm->DefineProperty
+    ("INTERFACE_COMPILE_OPTIONS", cmProperty::TARGET,
+     "List of interface options to pass to the compiler.",
+     "Targets may populate this property to publish the compile options "
+     "required to compile against the headers for the target.  Consuming "
+     "targets can add entries to their own COMPILE_OPTIONS property such "
+     "as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_OPTIONS> to use the "
+     "compile options specified in the interface of 'foo'."
+     "\n"
+     CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+     CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
+
+  cm->DefineProperty
     ("DEFINE_SYMBOL", cmProperty::TARGET,
      "Define a symbol when compiling this target's sources.",
      "DEFINE_SYMBOL sets the name of the preprocessor symbol defined when "
@@ -2731,6 +2763,17 @@ void cmTarget::SetProperty(const char* prop, const char* value)
                           new cmTargetInternals::TargetPropertyEntry(cge));
     return;
     }
+  if(strcmp(prop,"COMPILE_OPTIONS") == 0)
+    {
+    cmListFileBacktrace lfbt;
+    this->Makefile->GetBacktrace(lfbt);
+    cmGeneratorExpression ge(lfbt);
+    deleteAndClear(this->Internal->CompileOptionsEntries);
+    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+    this->Internal->CompileOptionsEntries.push_back(
+                          new cmTargetInternals::TargetPropertyEntry(cge));
+    return;
+    }
   if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
     {
     cmOStringStream e;
@@ -2773,6 +2816,15 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
               new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
     return;
     }
+  if(strcmp(prop,"COMPILE_OPTIONS") == 0)
+    {
+    cmListFileBacktrace lfbt;
+    this->Makefile->GetBacktrace(lfbt);
+    cmGeneratorExpression ge(lfbt);
+    this->Internal->CompileOptionsEntries.push_back(
+              new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
+    return;
+    }
   if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
     {
     cmOStringStream e;
@@ -3094,6 +3146,159 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
 }
 
 //----------------------------------------------------------------------------
+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)
+{
+  cmMakefile *mf = tgt->GetMakefile();
+
+  for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
+      it = entries.begin(), end = entries.end(); it != end; ++it)
+    {
+    bool cacheOptions = false;
+    std::vector<std::string> entryOptions = (*it)->CachedEntries;
+    if(entryOptions.empty())
+      {
+      cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
+                                                config,
+                                                false,
+                                                tgt,
+                                                dagChecker),
+                                      entryOptions);
+      if (mf->IsGeneratingBuildSystem()
+          && !(*it)->ge->GetHadContextSensitiveCondition())
+        {
+        cacheOptions = true;
+        }
+      }
+    std::string usedOptions;
+    for(std::vector<std::string>::iterator
+          li = entryOptions.begin(); li != entryOptions.end(); ++li)
+      {
+      std::string opt = *li;
+
+      if(uniqueOptions.insert(opt).second)
+        {
+        options.push_back(opt);
+        if (debugOptions)
+          {
+          usedOptions += " * " + opt + "\n";
+          }
+        }
+      }
+    if (cacheOptions)
+      {
+      (*it)->CachedEntries = entryOptions;
+      }
+    if (!usedOptions.empty())
+      {
+      mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
+                            std::string("Used compile options for target ")
+                            + tgt->GetName() + ":\n"
+                            + usedOptions, (*it)->ge->GetBacktrace());
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::GetCompileOptions(std::vector<std::string> &result,
+                                 const char *config)
+{
+  std::set<std::string> uniqueOptions;
+  cmListFileBacktrace lfbt;
+
+  cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+                                              this->GetName(),
+                                              "COMPILE_OPTIONS", 0, 0);
+
+  std::vector<std::string> debugProperties;
+  const char *debugProp =
+              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+  if (debugProp)
+    {
+    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+    }
+
+  bool debugOptions = !this->DebugCompileOptionsDone
+                    && std::find(debugProperties.begin(),
+                                 debugProperties.end(),
+                                 "COMPILE_OPTIONS")
+                        != debugProperties.end();
+
+  if (this->Makefile->IsGeneratingBuildSystem())
+    {
+    this->DebugCompileOptionsDone = true;
+    }
+
+  processCompileOptions(this,
+                            this->Internal->CompileOptionsEntries,
+                            result,
+                            uniqueOptions,
+                            &dagChecker,
+                            config,
+                            debugOptions);
+
+  std::string configString = config ? config : "";
+  if (!this->Internal->CacheLinkInterfaceCompileOptionsDone[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 optionGenex = "$<TARGET_PROPERTY:" +
+                              it->Value + ",INTERFACE_COMPILE_OPTIONS>";
+      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.
+        optionGenex = "$<$<BOOL:" + it->Value + ">:" + optionGenex + ">";
+        }
+      cmGeneratorExpression ge(it->Backtrace);
+      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
+                                                                optionGenex);
+
+      this->Internal
+        ->CachedLinkInterfaceCompileOptionsEntries[configString].push_back(
+                        new cmTargetInternals::TargetPropertyEntry(cge,
+                                                              it->Value));
+      }
+    }
+
+  processCompileOptions(this,
+    this->Internal->CachedLinkInterfaceCompileOptionsEntries[configString],
+                            result,
+                            uniqueOptions,
+                            &dagChecker,
+                            config,
+                            debugOptions);
+
+  if (!this->Makefile->IsGeneratingBuildSystem())
+    {
+    deleteAndClear(this->Internal->CachedLinkInterfaceCompileOptionsEntries);
+    }
+  else
+    {
+    this->Internal->CacheLinkInterfaceCompileOptionsDone[configString] = true;
+    }
+}
+
+//----------------------------------------------------------------------------
 std::string cmTarget::GetCompileDefinitions(const char *config)
 {
   const char *configProp = 0;
@@ -3525,6 +3730,24 @@ const char *cmTarget::GetProperty(const char* prop,
       }
     return output.c_str();
     }
+  if(strcmp(prop,"COMPILE_OPTIONS") == 0)
+    {
+    static std::string output;
+    output = "";
+    std::string sep;
+    typedef cmTargetInternals::TargetPropertyEntry
+                                TargetPropertyEntry;
+    for (std::vector<TargetPropertyEntry*>::const_iterator
+        it = this->Internal->CompileOptionsEntries.begin(),
+        end = this->Internal->CompileOptionsEntries.end();
+        it != end; ++it)
+      {
+      output += sep;
+      output += (*it)->ge->GetInput();
+      sep = ";";
+      }
+    return output.c_str();
+    }
 
   if (strcmp(prop,"IMPORTED") == 0)
     {
@@ -6109,6 +6332,7 @@ cmTargetInternalPointer
 cmTargetInternalPointer::~cmTargetInternalPointer()
 {
   deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
+  deleteAndClear(this->Pointer->CompileOptionsEntries);
   delete this->Pointer;
 }
 
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 508fc11..7ec10df 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -503,6 +503,9 @@ public:
 
   void AppendBuildInterfaceIncludes();
 
+  void GetCompileOptions(std::vector<std::string> &result,
+                         const char *config);
+
   bool IsNullImpliedByLinkLibraries(const std::string &p);
   bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
                                             const char *config);
@@ -627,6 +630,7 @@ private:
   bool IsApple;
   bool IsImportedTarget;
   bool DebugIncludesDone;
+  bool DebugCompileOptionsDone;
   mutable std::set<std::string> LinkImplicitNullProperties;
   bool BuildInterfaceIncludesAppended;
 
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 0b221e8..3a28be2 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -245,6 +245,7 @@ if(BUILD_TESTING)
   ADD_TEST_MACRO(PolicyScope PolicyScope)
   ADD_TEST_MACRO(EmptyLibrary EmptyLibrary)
   ADD_TEST_MACRO(CompileDefinitions CompileDefinitions)
+  ADD_TEST_MACRO(CompileOptions CompileOptions)
   ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
   set_tests_properties(EmptyLibrary PROPERTIES
     PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target:test")
diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt
new file mode 100644
index 0000000..6d8a96a
--- /dev/null
+++ b/Tests/CompileOptions/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(CompileOptions)
+
+add_library(testlib other.cpp)
+
+add_executable(CompileOptions main.cpp)
+set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:GNU>:-DTEST_DEFINE>")
+target_link_libraries(CompileOptions testlib)
+
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+  target_compile_definitions(CompileOptions
+    PRIVATE
+      "DO_GNU_TESTS"
+  )
+endif()
diff --git a/Tests/CompileOptions/main.cpp b/Tests/CompileOptions/main.cpp
new file mode 100644
index 0000000..0d39050
--- /dev/null
+++ b/Tests/CompileOptions/main.cpp
@@ -0,0 +1,11 @@
+
+#ifdef DO_GNU_TESTS
+#  ifndef TEST_DEFINE
+#    error Expected TEST_DEFINE
+#  endif
+#endif
+
+int main(int argc, char **argv)
+{
+  return 0;
+}
diff --git a/Tests/CompileOptions/other.cpp b/Tests/CompileOptions/other.cpp
new file mode 100644
index 0000000..0e34375
--- /dev/null
+++ b/Tests/CompileOptions/other.cpp
@@ -0,0 +1,5 @@
+
+void foo(void)
+{
+
+}

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7cb23084b2595d06aea46cead0e077b5f13aeddb
commit 7cb23084b2595d06aea46cead0e077b5f13aeddb
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue May 28 12:39:32 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Sun Jun 2 11:56:37 2013 +0200

    cmTarget: Rename LinkInterfaceIncludeDirectoriesEntries
    
    This can be used for COMPILE_OPTIONS too.

diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index e728c55..a54f80b 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -140,7 +140,7 @@ public:
     const std::string TargetName;
   };
   std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
-  std::vector<cmValueWithOrigin> LinkInterfaceIncludeDirectoriesEntries;
+  std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
 
   std::map<std::string, std::vector<TargetPropertyEntry*> >
                                 CachedLinkInterfaceIncludeDirectoriesEntries;
@@ -2741,14 +2741,14 @@ void cmTarget::SetProperty(const char* prop, const char* value)
     }
   if (strcmp(prop, "LINK_LIBRARIES") == 0)
     {
-    this->Internal->LinkInterfaceIncludeDirectoriesEntries.clear();
+    this->Internal->LinkInterfacePropertyEntries.clear();
     if (cmGeneratorExpression::IsValidTargetName(value)
         || cmGeneratorExpression::Find(value) != std::string::npos)
       {
       cmListFileBacktrace lfbt;
       this->Makefile->GetBacktrace(lfbt);
       cmValueWithOrigin entry(value, lfbt);
-      this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry);
+      this->Internal->LinkInterfacePropertyEntries.push_back(entry);
       }
     // Fall through
     }
@@ -2789,7 +2789,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
       cmListFileBacktrace lfbt;
       this->Makefile->GetBacktrace(lfbt);
       cmValueWithOrigin entry(value, lfbt);
-      this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry);
+      this->Internal->LinkInterfacePropertyEntries.push_back(entry);
       }
     // Fall through
     }
@@ -3036,8 +3036,8 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
   if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString])
     {
     for (std::vector<cmValueWithOrigin>::const_iterator
-        it = this->Internal->LinkInterfaceIncludeDirectoriesEntries.begin(),
-        end = this->Internal->LinkInterfaceIncludeDirectoriesEntries.end();
+        it = this->Internal->LinkInterfacePropertyEntries.begin(),
+        end = this->Internal->LinkInterfacePropertyEntries.end();
         it != end; ++it)
       {
       {

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=47f80d9c43eaa31c32b33a977bdbeda319671dd6
commit 47f80d9c43eaa31c32b33a977bdbeda319671dd6
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue May 28 12:32:39 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Sun Jun 2 11:56:36 2013 +0200

    cmTarget: Rename struct to be more re-usable.
    
    The same struct can be used to represent COMPILE_OPTIONS content.

diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 75873ff..e728c55 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -130,19 +130,19 @@ public:
   typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
   SourceEntriesType SourceEntries;
 
-  struct IncludeDirectoriesEntry {
-    IncludeDirectoriesEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
+  struct TargetPropertyEntry {
+    TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
       const std::string &targetName = std::string())
       : ge(cge), TargetName(targetName)
     {}
     const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
-    std::vector<std::string> CachedIncludes;
+    std::vector<std::string> CachedEntries;
     const std::string TargetName;
   };
-  std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
+  std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
   std::vector<cmValueWithOrigin> LinkInterfaceIncludeDirectoriesEntries;
 
-  std::map<std::string, std::vector<IncludeDirectoriesEntry*> >
+  std::map<std::string, std::vector<TargetPropertyEntry*> >
                                 CachedLinkInterfaceIncludeDirectoriesEntries;
   std::map<std::string, std::string> CachedLinkInterfaceCompileDefinitions;
 
@@ -152,9 +152,9 @@ public:
 
 //----------------------------------------------------------------------------
 void deleteAndClear(
-      std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries)
+      std::vector<cmTargetInternals::TargetPropertyEntry*> &entries)
 {
-  for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+  for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
       it = entries.begin(),
       end = entries.end();
       it != end; ++it)
@@ -167,10 +167,10 @@ void deleteAndClear(
 //----------------------------------------------------------------------------
 void deleteAndClear(
   std::map<std::string,
-          std::vector<cmTargetInternals::IncludeDirectoriesEntry*> > &entries)
+          std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries)
 {
   for (std::map<std::string,
-          std::vector<cmTargetInternals::IncludeDirectoriesEntry*> >::iterator
+          std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator
         it = entries.begin(), end = entries.end(); it != end; ++it)
     {
     deleteAndClear(it->second);
@@ -2728,7 +2728,7 @@ void cmTarget::SetProperty(const char* prop, const char* value)
     deleteAndClear(this->Internal->IncludeDirectoriesEntries);
     cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
     this->Internal->IncludeDirectoriesEntries.push_back(
-                          new cmTargetInternals::IncludeDirectoriesEntry(cge));
+                          new cmTargetInternals::TargetPropertyEntry(cge));
     return;
     }
   if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
@@ -2770,7 +2770,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
     this->Makefile->GetBacktrace(lfbt);
     cmGeneratorExpression ge(lfbt);
     this->Internal->IncludeDirectoriesEntries.push_back(
-              new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value)));
+              new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
     return;
     }
   if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
@@ -2854,17 +2854,17 @@ void cmTarget::InsertInclude(const cmValueWithOrigin &entry,
 {
   cmGeneratorExpression ge(entry.Backtrace);
 
-  std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::iterator position
+  std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
                 = before ? this->Internal->IncludeDirectoriesEntries.begin()
                          : this->Internal->IncludeDirectoriesEntries.end();
 
   this->Internal->IncludeDirectoriesEntries.insert(position,
-      new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value)));
+      new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
 }
 
 //----------------------------------------------------------------------------
 static void processIncludeDirectories(cmTarget *tgt,
-      const std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries,
+      const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
       std::vector<std::string> &includes,
       std::set<std::string> &uniqueIncludes,
       cmGeneratorExpressionDAGChecker *dagChecker,
@@ -2872,12 +2872,12 @@ static void processIncludeDirectories(cmTarget *tgt,
 {
   cmMakefile *mf = tgt->GetMakefile();
 
-  for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+  for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
       it = entries.begin(), end = entries.end(); it != end; ++it)
     {
     bool testIsOff = true;
     bool cacheIncludes = false;
-    std::vector<std::string> entryIncludes = (*it)->CachedIncludes;
+    std::vector<std::string> entryIncludes = (*it)->CachedEntries;
     if(!entryIncludes.empty())
       {
       testIsOff = false;
@@ -2980,7 +2980,7 @@ static void processIncludeDirectories(cmTarget *tgt,
       }
     if (cacheIncludes)
       {
-      (*it)->CachedIncludes = entryIncludes;
+      (*it)->CachedEntries = entryIncludes;
       }
     if (!usedIncludes.empty())
       {
@@ -3066,7 +3066,7 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
 
       this->Internal
         ->CachedLinkInterfaceIncludeDirectoriesEntries[configString].push_back(
-                        new cmTargetInternals::IncludeDirectoriesEntry(cge,
+                        new cmTargetInternals::TargetPropertyEntry(cge,
                                                               it->Value));
       }
     }
@@ -3512,9 +3512,9 @@ const char *cmTarget::GetProperty(const char* prop,
     static std::string output;
     output = "";
     std::string sep;
-    typedef cmTargetInternals::IncludeDirectoriesEntry
-                                IncludeDirectoriesEntry;
-    for (std::vector<IncludeDirectoriesEntry*>::const_iterator
+    typedef cmTargetInternals::TargetPropertyEntry
+                                TargetPropertyEntry;
+    for (std::vector<TargetPropertyEntry*>::const_iterator
         it = this->Internal->IncludeDirectoriesEntries.begin(),
         end = this->Internal->IncludeDirectoriesEntries.end();
         it != end; ++it)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1319a147bdc15f4a5a6a8dc56f0198600ff04c42
commit 1319a147bdc15f4a5a6a8dc56f0198600ff04c42
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue May 28 12:17:25 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Sun Jun 2 11:56:36 2013 +0200

    Add <LANG>_COMPILER_ID generator expressions.
    
    These expressions evaluate to the id of the compiler used to build
    the target, or can be used to test if the compiler id matches a
    specified value.

diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 656810d..a8b3847 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -40,6 +40,14 @@
   "is exported using export(), or when the target is used by another "  \
   "target in the same buildsystem. Expands to the empty string "        \
   "otherwise.\n"                                                        \
+  "  $<C_COMPILER_ID>          = The CMake-id of the C compiler "       \
+  "used.\n"                                                             \
+  "  $<C_COMPILER_ID:comp>     = '1' if the CMake-id of the C "         \
+  "compiler matches comp, otherwise '0'.\n"                             \
+  "  $<CXX_COMPILER_ID>          = The CMake-id of the CXX compiler "   \
+  "used.\n"                                                             \
+  "  $<CXX_COMPILER_ID:comp>     = '1' if the CMake-id of the CXX "     \
+  "compiler matches comp, otherwise '0'.\n"                             \
   "  $<TARGET_FILE:tgt>        = main file (.exe, .so.1.2, .a)\n"       \
   "  $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n"   \
   "  $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n"            \
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index df52368..f27761a 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -247,6 +247,104 @@ static const struct SemicolonNode : public cmGeneratorExpressionNode
 } semicolonNode;
 
 //----------------------------------------------------------------------------
+struct CompilerIdNode : public cmGeneratorExpressionNode
+{
+  CompilerIdNode() {}
+
+  virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
+
+  std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *context,
+                       const GeneratorExpressionContent *content,
+                       cmGeneratorExpressionDAGChecker *,
+                       const std::string &lang) const
+  {
+    const char *compilerId = context->Makefile ?
+                              context->Makefile->GetSafeDefinition((
+                              "CMAKE_" + lang + "_COMPILER_ID").c_str()) : "";
+    if (parameters.size() == 0)
+      {
+      return compilerId ? compilerId : "";
+      }
+    else
+    {
+    cmsys::RegularExpression compilerIdValidator;
+    compilerIdValidator.compile("^[A-Za-z0-9_]*$");
+    if (!compilerIdValidator.find(parameters.begin()->c_str()))
+      {
+      reportError(context, content->GetOriginalExpression(),
+                  "Expression syntax not recognized.");
+      return std::string();
+      }
+    if (!compilerId)
+      {
+      return parameters.front().empty() ? "1" : "0";
+      }
+
+    if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0)
+      {
+      return "1";
+      }
+    return "0";
+    }
+  }
+};
+
+//----------------------------------------------------------------------------
+static const struct CCompilerIdNode : public CompilerIdNode
+{
+  CCompilerIdNode() {}
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *context,
+                       const GeneratorExpressionContent *content,
+                       cmGeneratorExpressionDAGChecker *dagChecker) const
+  {
+    if (parameters.size() != 0 && parameters.size() != 1)
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<C_COMPILER_ID> expression requires one or two parameters");
+      return std::string();
+      }
+    if (!context->HeadTarget)
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<C_COMPILER_ID> may only be used with targets.  It may not "
+          "be used with add_custom_command.");
+      }
+    return this->EvaluateWithLanguage(parameters, context, content,
+                                      dagChecker, "C");
+  }
+} cCompilerIdNode;
+
+//----------------------------------------------------------------------------
+static const struct CXXCompilerIdNode : public CompilerIdNode
+{
+  CXXCompilerIdNode() {}
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *context,
+                       const GeneratorExpressionContent *content,
+                       cmGeneratorExpressionDAGChecker *dagChecker) const
+  {
+    if (parameters.size() != 0 && parameters.size() != 1)
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<CXX_COMPILER_ID> expression requires one or two parameters");
+      return std::string();
+      }
+    if (!context->HeadTarget)
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<CXX_COMPILER_ID> may only be used with targets.  It may not "
+          "be used with add_custom_command.");
+      }
+    return this->EvaluateWithLanguage(parameters, context, content,
+                                      dagChecker, "CXX");
+  }
+} cxxCompilerIdNode;
+
+//----------------------------------------------------------------------------
 static const struct ConfigurationNode : public cmGeneratorExpressionNode
 {
   ConfigurationNode() {}
@@ -1055,6 +1153,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     return &orNode;
   else if (identifier == "NOT")
     return &notNode;
+  else if (identifier == "C_COMPILER_ID")
+    return &cCompilerIdNode;
+  else if (identifier == "CXX_COMPILER_ID")
+    return &cxxCompilerIdNode;
   else if (identifier == "CONFIGURATION")
     return &configurationNode;
   else if (identifier == "CONFIG")

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=35496761a58956bd8c5ad65a3ed9ee78d09af56b
commit 35496761a58956bd8c5ad65a3ed9ee78d09af56b
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu May 16 14:59:04 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Sun Jun 2 11:56:36 2013 +0200

    Add cmLocalGenerator::GetCompileOptions.
    
    Currently it only adds the contents of the COMPILE_FLAGS target
    property, but it can be extended to handle a new COMPILE_OPTIONS
    generator expression enabled property.

diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 62e9194..29d86a6 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -429,7 +429,9 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source,
   lg->AppendFlags(flags, makefile->GetDefineFlags());
 
   // Add target-specific flags.
-  if(target->GetProperty("COMPILE_FLAGS"))
+  std::string targetFlags;
+  lg->GetCompileOptions(targetFlags, target, config);
+  if (!targetFlags.empty())
     {
     std::string langIncludeExpr = "CMAKE_";
     langIncludeExpr += language;
@@ -440,7 +442,7 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source,
       cmsys::RegularExpression r(regex);
       std::vector<std::string> args;
       cmSystemTools::
-        ParseWindowsCommandLine(target->GetProperty("COMPILE_FLAGS"), args);
+        ParseWindowsCommandLine(targetFlags.c_str(), args);
       for(std::vector<std::string>::iterator i = args.begin();
           i != args.end(); ++i)
         {
@@ -452,7 +454,7 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source,
       }
     else
       {
-      lg->AppendFlags(flags, target->GetProperty("COMPILE_FLAGS"));
+      lg->AppendFlags(flags, targetFlags.c_str());
       }
     }
 
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index bb1e792..10de35a 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -681,9 +681,11 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
 {
   // Add flags from target and source file properties.
   std::string flags;
-  if(cmtarget.GetProperty("COMPILE_FLAGS"))
+  std::string targetFlags;
+  lg->GetCompileOptions(targetFlags, &cmtarget, 0); // TODO: Config?
+  if(!targetFlags.empty())
     {
-    lg->AppendFlags(flags, cmtarget.GetProperty("COMPILE_FLAGS"));
+    lg->AppendFlags(flags, targetFlags.c_str());
     }
   const char* srcfmt = sf->GetProperty("Fortran_FORMAT");
   switch(this->CurrentLocalGenerator->GetFortranFormat(srcfmt))
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index d346f16..9429450 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1325,6 +1325,18 @@ std::string cmLocalGenerator::GetIncludeFlags(
 }
 
 //----------------------------------------------------------------------------
+void cmLocalGenerator::GetCompileOptions(std::string& flags,
+                                             cmTarget* target,
+                                             const char *config)
+{
+  // Add target-specific flags.
+  if(const char *prop = target->GetProperty("COMPILE_FLAGS"))
+    {
+    this->AppendFlags(flags, prop);
+    }
+}
+
+//----------------------------------------------------------------------------
 void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
                                              cmGeneratorTarget* target,
                                              const char* lang,
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index a1c34f0..28c88e6 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -215,6 +215,9 @@ public:
                              cmGeneratorTarget* target,
                              const char* lang = "C", const char *config = 0,
                              bool stripImplicitInclDirs = true);
+  void GetCompileOptions(std::string& flags,
+                         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/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 0a3728b..4c78f7f 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -1686,12 +1686,31 @@ void cmLocalVisualStudio6Generator
       flags += " /D \"_MBCS\"";
       }
 
+    {
+    std::string targetFlags;
+    this->GetCompileOptions(targetFlags, &target, 0);
     // Add per-target flags.
-    if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS"))
+    if(!targetFlags.empty())
       {
       flags += " ";
       flags += targetFlags;
       }
+    }
+#define ADD_FLAGS(CONFIG) \
+    { \
+    std::string targetFlags; \
+    this->GetCompileOptions(targetFlags, &target, #CONFIG); \
+    if(!targetFlags.empty()) \
+      { \
+      flags ## CONFIG += " "; \
+      flags ## CONFIG += targetFlags; \
+      } \
+    }
+
+    ADD_FLAGS(Debug)
+    ADD_FLAGS(Release)
+    ADD_FLAGS(MinSizeRel)
+    ADD_FLAGS(RelWithDebInfo)
 
     // Add per-target and per-configuration preprocessor definitions.
     std::set<std::string> definesSet;
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 58d28da..e7badf0 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -723,8 +723,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
       }
     }
 
+  std::string targetFlags;
+  this->GetCompileOptions(targetFlags, &target, configName);
   // Add the target-specific flags.
-  if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS"))
+  if(!targetFlags.empty())
     {
     flags += " ";
     flags += targetFlags;
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 4220ae1..d83d722 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -332,21 +332,25 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
       this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n";
     }
 
+  std::string targetFlags;
   for(std::set<cmStdString>::const_iterator l = languages.begin();
       l != languages.end(); ++l)
     {
     *this->FlagFileStream << *l << "_FLAGS = " << this->GetFlags(*l) << "\n\n";
     *this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) <<
       "\n\n";
+    std::string targetLangFlags;
+    this->LocalGenerator->GetCompileOptions(targetLangFlags, this->Target,
+                            this->LocalGenerator->ConfigurationName.c_str());
+    if (!targetFlags.empty() && targetFlags != targetLangFlags)
+      {
+      targetFlags += " " + targetLangFlags;
+      }
     }
 
-  // Add target-specific flags.
-  if(this->Target->GetProperty("COMPILE_FLAGS"))
+  if (!targetFlags.empty())
     {
-    std::string flags;
-    this->LocalGenerator->AppendFlags
-      (flags, this->Target->GetProperty("COMPILE_FLAGS"));
-    *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n";
+    *this->FlagFileStream << "# TARGET_FLAGS = " << targetFlags << "\n\n";
     }
 }
 
@@ -532,8 +536,13 @@ cmMakefileTargetGenerator
   langFlags += "_FLAGS)";
   this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
 
-  // Add target-specific flags.
-  if(this->Target->GetProperty("COMPILE_FLAGS"))
+  std::string configUpper =
+    cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
+
+  std::string targetFlags;
+  this->LocalGenerator->GetCompileOptions(targetFlags, this->Target,
+                                          configUpper.c_str());
+  if (!targetFlags.empty())
     {
     std::string langIncludeExpr = "CMAKE_";
     langIncludeExpr += lang;
@@ -545,7 +554,7 @@ cmMakefileTargetGenerator
       cmsys::RegularExpression r(regex);
       std::vector<std::string> args;
       cmSystemTools::ParseWindowsCommandLine(
-        this->Target->GetProperty("COMPILE_FLAGS"),
+        targetFlags.c_str(),
         args);
       for(std::vector<std::string>::iterator i = args.begin();
           i != args.end(); ++i)
@@ -559,8 +568,7 @@ cmMakefileTargetGenerator
       }
     else
       {
-      this->LocalGenerator->AppendFlags
-        (flags, this->Target->GetProperty("COMPILE_FLAGS"));
+      this->LocalGenerator->AppendFlags(flags, targetFlags.c_str());
       }
     }
 
@@ -594,8 +602,6 @@ cmMakefileTargetGenerator
                           << compile_defs << "\n"
                           << "\n";
     }
-  std::string configUpper =
-    cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
   std::string defPropName = "COMPILE_DEFINITIONS_";
   defPropName += configUpper;
   if(const char* config_compile_defs =
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 850e5ea..141e014 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -151,9 +151,9 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
                                         this->GetConfigName());
 
   // Add include directory flags.
+  const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
   {
   std::vector<std::string> includes;
-  const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
   this->LocalGenerator->GetIncludeDirectories(includes,
                                               this->GeneratorTarget,
                                               language.c_str(), config);
@@ -171,7 +171,9 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
   this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags());
 
   // Add target-specific flags.
-  if(this->Target->GetProperty("COMPILE_FLAGS"))
+  std::string targetFlags;
+  this->LocalGenerator->GetCompileOptions(targetFlags, this->Target, config);
+  if(!targetFlags.empty())
     {
     std::string langIncludeExpr = "CMAKE_";
     langIncludeExpr += language;
@@ -183,7 +185,7 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
       cmsys::RegularExpression r(regex);
       std::vector<std::string> args;
       cmSystemTools::ParseWindowsCommandLine(
-        this->Target->GetProperty("COMPILE_FLAGS"),
+        targetFlags.c_str(),
         args);
       for(std::vector<std::string>::iterator i = args.begin();
           i != args.end(); ++i)
@@ -198,7 +200,7 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
     else
       {
       this->LocalGenerator->AppendFlags
-        (flags, this->Target->GetProperty("COMPILE_FLAGS"));
+        (flags, targetFlags.c_str());
       }
     }
 
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 88c4deb..341ef45 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1261,8 +1261,12 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
       flags += " /TP ";
       }
     }
+
+  std::string targetFlags;
+  this->LocalGenerator->GetCompileOptions(targetFlags, this->Target,
+                                          configName.c_str());
   // Add the target-specific flags.
-  if(const char* targetFlags = this->Target->GetProperty("COMPILE_FLAGS"))
+  if(!targetFlags.empty())
     {
     flags += " ";
     flags += targetFlags;

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f3ad863ae6f0487bbf80d95b0d3f622840187a6a
commit f3ad863ae6f0487bbf80d95b0d3f622840187a6a
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue May 28 17:44:35 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Sun Jun 2 11:56:36 2013 +0200

    VS6: Rename some variables to correspond to config values.
    
    This simplifies population of the compile flags.

diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index dc94476..0a3728b 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -1639,9 +1639,9 @@ void cmLocalVisualStudio6Generator
     // store flags for each configuration
     std::string flags = " ";
     std::string flagsRelease = " ";
-    std::string flagsMinSize = " ";
+    std::string flagsMinSizeRel = " ";
     std::string flagsDebug = " ";
-    std::string flagsDebugRel = " ";
+    std::string flagsRelWithDebInfo = " ";
     if(target.GetType() >= cmTarget::EXECUTABLE &&
        target.GetType() <= cmTarget::OBJECT_LIBRARY)
       {
@@ -1664,16 +1664,16 @@ void cmLocalVisualStudio6Generator
       flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" ";
 
       flagVar = baseFlagVar + "_MINSIZEREL";
-      flagsMinSize = this->Makefile->GetSafeDefinition(flagVar.c_str());
-      flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
+      flagsMinSizeRel = this->Makefile->GetSafeDefinition(flagVar.c_str());
+      flagsMinSizeRel += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
 
       flagVar = baseFlagVar + "_DEBUG";
       flagsDebug = this->Makefile->GetSafeDefinition(flagVar.c_str());
       flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" ";
 
       flagVar = baseFlagVar + "_RELWITHDEBINFO";
-      flagsDebugRel = this->Makefile->GetSafeDefinition(flagVar.c_str());
-      flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
+      flagsRelWithDebInfo = this->Makefile->GetSafeDefinition(flagVar.c_str());
+      flagsRelWithDebInfo += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
       }
 
     // if _UNICODE and _SBCS are not found, then add -D_MBCS
@@ -1731,19 +1731,19 @@ void cmLocalVisualStudio6Generator
     flags += defines;
     flagsDebug += debugDefines;
     flagsRelease += releaseDefines;
-    flagsMinSize += minsizeDefines;
-    flagsDebugRel += debugrelDefines;
+    flagsMinSizeRel += minsizeDefines;
+    flagsRelWithDebInfo += debugrelDefines;
 
     // The template files have CXX FLAGS in them, that need to be replaced.
     // There are not separate CXX and C template files, so we use the same
     // variable names.   The previous code sets up flags* variables to contain
     // the correct C or CXX flags
     cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL",
-                                 flagsMinSize.c_str());
+                                 flagsMinSizeRel.c_str());
     cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG",
                                  flagsDebug.c_str());
     cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
-                                 flagsDebugRel.c_str());
+                                 flagsRelWithDebInfo.c_str());
     cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE",
                                  flagsRelease.c_str());
     cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());

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

Summary of changes:
 Source/CMakeVersion.cmake |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list