[Cmake-commits] CMake branch, next, updated. v3.2.0-851-g3ea132e

Stephen Kelly steveire at gmail.com
Thu Mar 5 14:03:05 EST 2015


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  3ea132eb29448001cf27544e3fd1e35fc4b0574b (commit)
       via  ccb0cd8aa281c21fc7d52f6ff02fba6ff22b80a4 (commit)
       via  c9c01afafa13d18be066442a88be86db42035b38 (commit)
       via  4b05997f20c68a689672a916ab635593cb6e5eed (commit)
       via  89e59bb7837fc98f30ef55e021196125b10faaa4 (commit)
      from  dc6cebe35f74b2fbc1b99434d04e454bdb6525f7 (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=3ea132eb29448001cf27544e3fd1e35fc4b0574b
commit 3ea132eb29448001cf27544e3fd1e35fc4b0574b
Merge: dc6cebe ccb0cd8
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu Mar 5 14:03:01 2015 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Thu Mar 5 14:03:01 2015 -0500

    Merge topic 'target-language-genex' into next
    
    ccb0cd8a File(GENERATE): Process genex evaluation files for each language.
    c9c01afa Genex: Allow COMPILE_LANGUAGE when processing include directories.
    4b05997f Genex: Allow COMPILE_LANGUAGE when processing compile definitions.
    89e59bb7 Genex: Enable use of COMPILE_LANGUAGE for compile options.


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ccb0cd8aa281c21fc7d52f6ff02fba6ff22b80a4
commit ccb0cd8aa281c21fc7d52f6ff02fba6ff22b80a4
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Feb 22 17:44:59 2015 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Mar 5 20:00:46 2015 +0100

    File(GENERATE): Process genex evaluation files for each language.

diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index 4e2a868..fa00283 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -38,13 +38,15 @@ cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
 
 //----------------------------------------------------------------------------
 void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
+              const std::string& lang,
               cmCompiledGeneratorExpression* inputExpression,
               std::map<std::string, std::string> &outputFiles, mode_t perm)
 {
   std::string rawCondition = this->Condition->GetInput();
   if (!rawCondition.empty())
     {
-    std::string condResult = this->Condition->Evaluate(this->Makefile, config);
+    std::string condResult = this->Condition->Evaluate(this->Makefile, config,
+                                                       false, 0, 0, 0, lang);
     if (condResult == "0")
       {
       return;
@@ -60,9 +62,11 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
     }
 
   const std::string outputFileName
-                    = this->OutputFileExpr->Evaluate(this->Makefile, config);
+                    = this->OutputFileExpr->Evaluate(this->Makefile, config,
+                                                     false, 0, 0, 0, lang);
   const std::string outputContent
-                          = inputExpression->Evaluate(this->Makefile, config);
+                          = inputExpression->Evaluate(this->Makefile, config,
+                                                      false, 0, 0, 0, lang);
 
   std::map<std::string, std::string>::iterator it
                                           = outputFiles.find(outputFileName);
@@ -75,7 +79,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
       }
     std::ostringstream e;
     e << "Evaluation file to be written multiple times for different "
-         "configurations with different content:\n  " << outputFileName;
+         "configurations or languages with different content:\n  "
+      << outputFileName;
     this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
     return;
     }
@@ -97,14 +102,22 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
 void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
                                               std::string const& config)
 {
-  std::string name = this->OutputFileExpr->Evaluate(this->Makefile, config);
-  cmSourceFile* sf = this->Makefile->GetOrCreateSource(name);
-  sf->SetProperty("GENERATED", "1");
-
+  std::vector<std::string> enabledLanguages;
   cmGlobalGenerator *gg
                   = this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
-  gg->SetFilenameTargetDepends(sf,
+  gg->GetEnabledLanguages(enabledLanguages);
+
+  for(std::vector<std::string>::const_iterator le = enabledLanguages.begin();
+      le != enabledLanguages.end(); ++le)
+    {
+    std::string name = this->OutputFileExpr->Evaluate(this->Makefile, config,
+                                                      false, 0, 0, 0, *le);
+    cmSourceFile* sf = this->Makefile->GetOrCreateSource(name);
+    sf->SetProperty("GENERATED", "1");
+
+    gg->SetFilenameTargetDepends(sf,
                           this->OutputFileExpr->GetSourceSensitiveTargets());
+    }
 }
 
 //----------------------------------------------------------------------------
@@ -153,13 +166,23 @@ void cmGeneratorExpressionEvaluationFile::Generate()
     {
     allConfigs.push_back("");
     }
-  for(std::vector<std::string>::const_iterator li = allConfigs.begin();
-      li != allConfigs.end(); ++li)
+
+  std::vector<std::string> enabledLanguages;
+  cmGlobalGenerator *gg
+                  = this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
+  gg->GetEnabledLanguages(enabledLanguages);
+
+  for(std::vector<std::string>::const_iterator le = enabledLanguages.begin();
+      le != enabledLanguages.end(); ++le)
     {
-    this->Generate(*li, inputExpression.get(), outputFiles, perm);
-    if(cmSystemTools::GetFatalErrorOccured())
+    for(std::vector<std::string>::const_iterator li = allConfigs.begin();
+        li != allConfigs.end(); ++li)
       {
-      return;
+      this->Generate(*li, *le, inputExpression.get(), outputFiles, perm);
+      if(cmSystemTools::GetFatalErrorOccured())
+        {
+        return;
+        }
       }
     }
 }
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
index 3394ade..4424bec 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.h
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -34,7 +34,7 @@ public:
   void CreateOutputFile(std::string const& config);
 
 private:
-  void Generate(const std::string& config,
+  void Generate(const std::string& config, const std::string& lang,
               cmCompiledGeneratorExpression* inputExpression,
               std::map<std::string, std::string> &outputFiles, mode_t perm);
 
diff --git a/Tests/RunCMake/File_Generate/COMPILE_LANGUAGE-genex-result.txt b/Tests/RunCMake/File_Generate/COMPILE_LANGUAGE-genex-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/COMPILE_LANGUAGE-genex-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/File_Generate/COMPILE_LANGUAGE-genex.cmake b/Tests/RunCMake/File_Generate/COMPILE_LANGUAGE-genex.cmake
new file mode 100644
index 0000000..e2b081d
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/COMPILE_LANGUAGE-genex.cmake
@@ -0,0 +1,12 @@
+
+enable_language(CXX C)
+
+add_library(empty empty.cpp empty.c)
+target_compile_options(empty
+  PRIVATE LANG_IS_$<COMPILE_LANGUAGE>
+)
+
+file(GENERATE
+  OUTPUT opts-$<COMPILE_LANGUAGE>.txt
+  CONTENT "$<TARGET_PROPERTY:empty,COMPILE_OPTIONS>\n"
+)
diff --git a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
index dbd39de..0abb7df 100644
--- a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
+++ b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
@@ -1,5 +1,5 @@
 CMake Error in CMakeLists.txt:
   Evaluation file to be written multiple times for different configurations
-  with different content:
+  or languages with different content:
 
   .*output.txt
diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
index 97f93d5..db344ef 100644
--- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
@@ -17,6 +17,16 @@ if (NOT file_contents MATCHES "generated.cpp.rule")
   message(SEND_ERROR "Rule file not in target sources! ${file_contents}")
 endif()
 
+if (NOT RunCMake_GENERATOR MATCHES "Visual Studio")
+  run_cmake(COMPILE_LANGUAGE-genex)
+  foreach(l CXX C)
+    file(READ "${RunCMake_BINARY_DIR}/COMPILE_LANGUAGE-genex-build/opts-${l}.txt" l_defs)
+    if (NOT l_defs STREQUAL "LANG_IS_${l}\n")
+      message(FATAL_ERROR "File content does not match: ${l_defs}")
+    endif()
+  endforeach()
+endif()
+
 set(timeformat "%Y%j%H%M%S")
 
 file(REMOVE "${RunCMake_BINARY_DIR}/WriteIfDifferent-build/output_file.txt")
diff --git a/Tests/RunCMake/File_Generate/empty.c b/Tests/RunCMake/File_Generate/empty.c
new file mode 100644
index 0000000..563eef0
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/empty.c
@@ -0,0 +1,8 @@
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty_c()
+{
+  return 0;
+}

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c9c01afafa13d18be066442a88be86db42035b38
commit c9c01afafa13d18be066442a88be86db42035b38
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Wed Mar 4 21:53:15 2015 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Mar 5 20:00:46 2015 +0100

    Genex: Allow COMPILE_LANGUAGE when processing include directories.
    
    Issue an error if this is encountered by an IDE generator.

diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index b6d97d1..d38cf7e 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -121,7 +121,8 @@ Available logical expressions are:
     target_link_libraries(myapp myapp_c myapp_cxx)
 
   The ``Makefile`` and ``Ninja`` based generators can also use this
-  expression to specify compile-language specific compile definitions:
+  expression to specify compile-language specific compile definitions
+  and include directories:
 
   .. code-block:: cmake
 
@@ -129,6 +130,9 @@ Available logical expressions are:
     target_compile_definitions(myapp
       PRIVATE $<$<COMPILE_LANGUAGE:CXX>:COMPILING_CXX>
     )
+    target_include_directories(myapp
+      PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/opt/foo/cxx_headers>
+    )
 
 Informational Expressions
 =========================
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 26ee7af..f289ead 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -850,7 +850,8 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
       }
     else if (gg->GetName().find("Xcode") != std::string::npos)
       {
-      if (dagChecker && dagChecker->EvaluatingCompileDefinitions())
+      if (dagChecker && (dagChecker->EvaluatingCompileDefinitions()
+          || dagChecker->EvaluatingIncludeDirectories()))
         {
         reportError(context, content->GetOriginalExpression(),
             "$<COMPILE_LANGUAGE:...> may only be used with COMPILE_OPTIONS "
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 44c9e9a..b7b2eff 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -960,9 +960,10 @@ cmGeneratorTarget::GetCreateRuleVariable(std::string const& lang,
 
 //----------------------------------------------------------------------------
 std::vector<std::string>
-cmGeneratorTarget::GetIncludeDirectories(const std::string& config) const
+cmGeneratorTarget::GetIncludeDirectories(const std::string& config,
+                                         const std::string& lang) const
 {
-  return this->Target->GetIncludeDirectories(config);
+  return this->Target->GetIncludeDirectories(config, lang);
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 2083b88..c329cf5 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -85,7 +85,7 @@ public:
 
   /** Get the include directories for this target.  */
   std::vector<std::string> GetIncludeDirectories(
-      const std::string& config) const;
+      const std::string& config, const std::string& lang) const;
 
   bool IsSystemIncludeDirectory(const std::string& dir,
                                 const std::string& config) const;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 735dfa9..37cc2c6 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1600,7 +1600,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
   // Get the target-specific include directories.
   std::vector<std::string> includes;
 
-  includes = target->GetIncludeDirectories(config);
+  includes = target->GetIncludeDirectories(config, lang);
 
   // Support putting all the in-project include directories first if
   // it is requested by the project.
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 9ecb029..50491af 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -2114,6 +2114,32 @@ void cmLocalUnixMakefileGenerator3
       cmakefileStream
         << "  )\n";
       }
+
+    // Target-specific include directories:
+    cmakefileStream
+      << "\n"
+      << "# The include file search paths:\n";
+    cmakefileStream
+      << "set(CMAKE_" << l->first << "_TARGET_INCLUDE_PATH\n";
+    std::vector<std::string> includes;
+
+    cmGeneratorTarget* gt = this->GetGlobalGenerator()
+                                ->GetGeneratorTarget(&target);
+
+    const std::string& config =
+      this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+    this->GetIncludeDirectories(includes, gt,
+                                l->first, config);
+    for(std::vector<std::string>::iterator i = includes.begin();
+        i != includes.end(); ++i)
+      {
+      cmakefileStream
+        << "  \""
+        << this->Convert(*i, cmLocalGenerator::HOME_OUTPUT)
+        << "\"\n";
+      }
+    cmakefileStream
+      << "  )\n";
     }
 
   // Store include transform rule properties.  Write the directory
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 57c49f1..c7a7110 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1056,40 +1056,6 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
       << "set(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
     }
 
-  // Target-specific include directories:
-  *this->InfoFileStream
-    << "\n"
-    << "# The include file search paths:\n";
-  *this->InfoFileStream
-    << "set(CMAKE_C_TARGET_INCLUDE_PATH\n";
-  std::vector<std::string> includes;
-
-  const std::string& config =
-    this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
-  this->LocalGenerator->GetIncludeDirectories(includes,
-                                              this->GeneratorTarget,
-                                              "C", config);
-  for(std::vector<std::string>::iterator i = includes.begin();
-      i != includes.end(); ++i)
-    {
-    *this->InfoFileStream
-      << "  \""
-      << this->LocalGenerator->Convert(*i,
-                                       cmLocalGenerator::HOME_OUTPUT)
-      << "\"\n";
-    }
-  *this->InfoFileStream
-    << "  )\n";
-  *this->InfoFileStream
-    << "set(CMAKE_CXX_TARGET_INCLUDE_PATH "
-    << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
-  *this->InfoFileStream
-    << "set(CMAKE_Fortran_TARGET_INCLUDE_PATH "
-    << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
-  *this->InfoFileStream
-    << "set(CMAKE_ASM_TARGET_INCLUDE_PATH "
-    << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
-
   // and now write the rule to use it
   std::vector<std::string> depends;
   std::vector<std::string> commands;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 87dcc99..7a6ad8b 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1979,7 +1979,8 @@ static void processIncludeDirectories(cmTarget const* tgt,
       std::vector<std::string> &includes,
       UNORDERED_SET<std::string> &uniqueIncludes,
       cmGeneratorExpressionDAGChecker *dagChecker,
-      const std::string& config, bool debugIncludes)
+      const std::string& config, bool debugIncludes,
+      const std::string& language)
 {
   cmMakefile *mf = tgt->GetMakefile();
 
@@ -1995,7 +1996,7 @@ static void processIncludeDirectories(cmTarget const* tgt,
                                               config,
                                               false,
                                               tgt,
-                                              dagChecker),
+                                              dagChecker, language),
                                     entryIncludes);
 
     std::string usedIncludes;
@@ -2106,7 +2107,8 @@ static void processIncludeDirectories(cmTarget const* tgt,
 
 //----------------------------------------------------------------------------
 std::vector<std::string>
-cmTarget::GetIncludeDirectories(const std::string& config) const
+cmTarget::GetIncludeDirectories(const std::string& config,
+                                const std::string& language) const
 {
   std::vector<std::string> includes;
   UNORDERED_SET<std::string> uniqueIncludes;
@@ -2139,7 +2141,8 @@ cmTarget::GetIncludeDirectories(const std::string& config) const
                             uniqueIncludes,
                             &dagChecker,
                             config,
-                            debugIncludes);
+                            debugIncludes,
+                            language);
 
   std::vector<cmTargetInternals::TargetPropertyEntry*>
     linkInterfaceIncludeDirectoriesEntries;
@@ -2179,7 +2182,8 @@ cmTarget::GetIncludeDirectories(const std::string& config) const
                             uniqueIncludes,
                             &dagChecker,
                             config,
-                            debugIncludes);
+                            debugIncludes,
+                            language);
 
   deleteAndClear(linkInterfaceIncludeDirectoriesEntries);
 
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 0356c1e..5170b31 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -568,7 +568,8 @@ public:
                                     bool contentOnly) const;
 
   std::vector<std::string> GetIncludeDirectories(
-                     const std::string& config) const;
+                     const std::string& config,
+                     const std::string& language) const;
   void InsertInclude(const cmValueWithOrigin &entry,
                      bool before = false);
   void InsertCompileOption(const cmValueWithOrigin &entry,
diff --git a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
index 661bbaa..d57556a 100644
--- a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
@@ -42,6 +42,20 @@ add_executable(consumer
   "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
 )
 
+if (CMAKE_GENERATOR MATCHES "Makefiles" OR CMAKE_GENERATOR MATCHES "Ninja")
+  target_sources(consumer PRIVATE
+    "${CMAKE_CURRENT_SOURCE_DIR}/consumer.c"
+  )
+  target_include_directories(consumer
+    PRIVATE
+      $<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/cxx_only>
+      $<$<COMPILE_LANGUAGE:C>:${CMAKE_CURRENT_SOURCE_DIR}/c_only>
+  )
+  target_compile_definitions(consumer
+    PRIVATE -DTEST_LANG_DEFINES
+  )
+endif()
+
 target_include_directories(consumer
   PRIVATE
     $<TARGET_PROPERTY:target_include_directories,INTERFACE_INCLUDE_DIRECTORIES>
diff --git a/Tests/CMakeCommands/target_include_directories/c_only/c_only.h b/Tests/CMakeCommands/target_include_directories/c_only/c_only.h
new file mode 100644
index 0000000..29f68ee
--- /dev/null
+++ b/Tests/CMakeCommands/target_include_directories/c_only/c_only.h
@@ -0,0 +1,2 @@
+
+#define C_ONLY_DEFINE
diff --git a/Tests/CMakeCommands/target_include_directories/consumer.c b/Tests/CMakeCommands/target_include_directories/consumer.c
new file mode 100644
index 0000000..8821f5b
--- /dev/null
+++ b/Tests/CMakeCommands/target_include_directories/consumer.c
@@ -0,0 +1,10 @@
+
+#ifdef TEST_LANG_DEFINES
+  #include "c_only.h"
+
+  #ifndef C_ONLY_DEFINE
+  #error Expected C_ONLY_DEFINE
+  #endif
+#endif
+
+int consumer_c() { return 0; }
diff --git a/Tests/CMakeCommands/target_include_directories/consumer.cpp b/Tests/CMakeCommands/target_include_directories/consumer.cpp
index 7e3443e..649510c 100644
--- a/Tests/CMakeCommands/target_include_directories/consumer.cpp
+++ b/Tests/CMakeCommands/target_include_directories/consumer.cpp
@@ -4,6 +4,9 @@
 #include "interfaceinclude.h"
 #include "relative_dir.h"
 #include "consumer.h"
+#ifdef TEST_LANG_DEFINES
+  #include "cxx_only.h"
+#endif
 
 #ifdef PRIVATEINCLUDE_DEFINE
 #error Unexpected PRIVATEINCLUDE_DEFINE
@@ -29,4 +32,10 @@
 #error Expected CONSUMER_DEFINE
 #endif
 
+#ifdef TEST_LANG_DEFINES
+  #ifndef CXX_ONLY_DEFINE
+  #error Expected CXX_ONLY_DEFINE
+  #endif
+#endif
+
 int main() { return 0; }
diff --git a/Tests/CMakeCommands/target_include_directories/cxx_only/cxx_only.h b/Tests/CMakeCommands/target_include_directories/cxx_only/cxx_only.h
new file mode 100644
index 0000000..67289a4
--- /dev/null
+++ b/Tests/CMakeCommands/target_include_directories/cxx_only/cxx_only.h
@@ -0,0 +1,2 @@
+
+#define CXX_ONLY_DEFINE
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-result.txt b/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-stderr-VS.txt b/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-stderr-VS.txt
new file mode 100644
index 0000000..ec15068
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-stderr-VS.txt
@@ -0,0 +1,8 @@
+CMake Error at IncludeDirectories.cmake:5 \(target_include_directories\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE:CXX>
+
+  \$<COMPILE_LANGUAGE:...> may not be used with Visual Studio generators.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-stderr-Xcode.txt b/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-stderr-Xcode.txt
new file mode 100644
index 0000000..fdf92b2
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-stderr-Xcode.txt
@@ -0,0 +1,9 @@
+CMake Error at IncludeDirectories.cmake:5 \(target_include_directories\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE:CXX>
+
+  \$<COMPILE_LANGUAGE:...> may only be used with COMPILE_OPTIONS with the
+  Xcode generator.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories.cmake b/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories.cmake
new file mode 100644
index 0000000..31771f6
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories.cmake
@@ -0,0 +1,5 @@
+
+enable_language(CXX)
+
+add_executable(main main.cpp)
+target_include_directories(main PRIVATE $<$<COMPILE_LANGUAGE:CXX>:anydir>)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake b/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake
index 8a32aef..5e0a5f5 100644
--- a/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake
@@ -11,3 +11,10 @@ elseif (RunCMake_GENERATOR MATCHES "Visual Studio")
     set(RunCMake-stderr-file CompileDefinitions-stderr-VS.txt)
     run_cmake(CompileDefinitions)
 endif()
+if (RunCMake_GENERATOR STREQUAL "Xcode")
+    set(RunCMake-stderr-file IncludeDirectories-stderr-Xcode.txt)
+    run_cmake(IncludeDirectories)
+elseif (RunCMake_GENERATOR MATCHES "Visual Studio")
+    set(RunCMake-stderr-file IncludeDirectories-stderr-VS.txt)
+    run_cmake(IncludeDirectories)
+endif()

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4b05997f20c68a689672a916ab635593cb6e5eed
commit 4b05997f20c68a689672a916ab635593cb6e5eed
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Wed Mar 4 21:46:42 2015 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Mar 5 20:00:46 2015 +0100

    Genex: Allow COMPILE_LANGUAGE when processing compile definitions.
    
    Issue an error if this is encountered by an IDE generator.

diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index b1b1102..b6d97d1 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -120,6 +120,16 @@ Available logical expressions are:
     add_executable(myapp main.cpp)
     target_link_libraries(myapp myapp_c myapp_cxx)
 
+  The ``Makefile`` and ``Ninja`` based generators can also use this
+  expression to specify compile-language specific compile definitions:
+
+  .. code-block:: cmake
+
+    add_executable(myapp main.cpp foo.c bar.cpp)
+    target_compile_definitions(myapp
+      PRIVATE $<$<COMPILE_LANGUAGE:CXX>:COMPILING_CXX>
+    )
+
 Informational Expressions
 =========================
 
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 69857ef..614e7d9 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -599,7 +599,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
 
     // the compilerdefines for this target
     std::vector<std::string> cdefs;
-    target->GetCompileDefinitions(cdefs, buildType);
+    target->GetCompileDefinitions(cdefs, buildType, "C");
 
     // Expand the list.
     for(std::vector<std::string>::const_iterator di = cdefs.begin();
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 5fff0fb..25f9005 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -436,7 +436,7 @@ ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg, cmTarget *target,
     }
 
   // Add preprocessor definitions for this target and configuration.
-  lg->AddCompileDefinitions(defines, target, config);
+  lg->AddCompileDefinitions(defines, target, config, language);
   lg->AppendDefines(defines, source->GetProperty("COMPILE_DEFINITIONS"));
   {
   std::string defPropName = "COMPILE_DEFINITIONS_";
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 89bdb5b..26ee7af 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -817,7 +817,7 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
   std::string Evaluate(const std::vector<std::string> &parameters,
                        cmGeneratorExpressionContext *context,
                        const GeneratorExpressionContent *content,
-                       cmGeneratorExpressionDAGChecker *) const
+                       cmGeneratorExpressionDAGChecker *dagChecker) const
   {
     if(context->Language.empty())
       {
@@ -848,11 +848,20 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
           "generators.");
       return std::string();
       }
+    else if (gg->GetName().find("Xcode") != std::string::npos)
+      {
+      if (dagChecker && dagChecker->EvaluatingCompileDefinitions())
+        {
+        reportError(context, content->GetOriginalExpression(),
+            "$<COMPILE_LANGUAGE:...> may only be used with COMPILE_OPTIONS "
+            "with the Xcode generator.");
+        return std::string();
+        }
+      }
     else
       {
       if(gg->GetName().find("Makefiles") == std::string::npos &&
-              gg->GetName().find("Ninja") == std::string::npos &&
-              gg->GetName().find("Xcode") == std::string::npos)
+              gg->GetName().find("Ninja") == std::string::npos)
         {
         reportError(context, content->GetOriginalExpression(),
             "$<COMPILE_LANGUAGE:...> not supported for this generator.");
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index e89161d..bd8a1f5 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1803,7 +1803,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
     }
   cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
   std::vector<std::string> targetDefines;
-  target.GetCompileDefinitions(targetDefines, configName);
+  target.GetCompileDefinitions(targetDefines, configName, "C");
   this->AppendDefines(ppDefs, targetDefines);
   buildSettings->AddAttribute
     ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index be82085..735dfa9 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1428,11 +1428,11 @@ std::string cmLocalGenerator::GetIncludeFlags(
 //----------------------------------------------------------------------------
 void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines,
                                              cmTarget const* target,
-                                             const std::string& config)
+                                             const std::string& config,
+                                             const std::string& lang)
 {
   std::vector<std::string> targetDefines;
-  target->GetCompileDefinitions(targetDefines,
-                               config);
+  target->GetCompileDefinitions(targetDefines, config, lang);
   this->AppendDefines(defines, targetDefines);
 }
 
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 3a9d5be..f1f0da1 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -239,7 +239,8 @@ public:
                          const std::string& lang, const std::string& config);
   void AddCompileDefinitions(std::set<std::string>& defines,
                              cmTarget const* target,
-                             const std::string& config);
+                             const std::string& config,
+                             const std::string& lang);
 
   /** Compute the language used to compile the given source file.  */
   std::string GetSourceFileLanguage(const cmSourceFile& source);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 432cb3a..9ecb029 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -2094,26 +2094,26 @@ void cmLocalUnixMakefileGenerator3
         << "set(CMAKE_" << l->first << "_COMPILER_ID \""
         << cid << "\")\n";
       }
-    }
 
-  // Build a list of preprocessor definitions for the target.
-  std::set<std::string> defines;
-  this->AddCompileDefinitions(defines, &target,
-                               this->ConfigurationName);
-  if(!defines.empty())
-    {
-    cmakefileStream
-      << "\n"
-      << "# Preprocessor definitions for this target.\n"
-      << "set(CMAKE_TARGET_DEFINITIONS\n";
-    for(std::set<std::string>::const_iterator di = defines.begin();
-        di != defines.end(); ++di)
+    // Build a list of preprocessor definitions for the target.
+    std::set<std::string> defines;
+    this->AddCompileDefinitions(defines, &target,
+                                this->ConfigurationName, l->first);
+    if(!defines.empty())
       {
       cmakefileStream
-        << "  " << this->EscapeForCMake(*di) << "\n";
+        << "\n"
+        << "# Preprocessor definitions for this target.\n"
+        << "set(CMAKE_TARGET_DEFINITIONS_" << l->first << "\n";
+      for(std::set<std::string>::const_iterator di = defines.begin();
+          di != defines.end(); ++di)
+        {
+        cmakefileStream
+          << "  " << this->EscapeForCMake(*di) << "\n";
+        }
+      cmakefileStream
+        << "  )\n";
       }
-    cmakefileStream
-      << "  )\n";
     }
 
   // Store include transform rule properties.  Write the directory
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 1d62093..db59da9 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -1779,11 +1779,15 @@ void cmLocalVisualStudio6Generator
     std::set<std::string> minsizeDefinesSet;
     std::set<std::string> debugrelDefinesSet;
 
-    this->AddCompileDefinitions(definesSet, &target, "");
-    this->AddCompileDefinitions(debugDefinesSet, &target, "DEBUG");
-    this->AddCompileDefinitions(releaseDefinesSet, &target, "RELEASE");
-    this->AddCompileDefinitions(minsizeDefinesSet, &target, "MINSIZEREL");
-    this->AddCompileDefinitions(debugrelDefinesSet, &target, "RELWITHDEBINFO");
+    this->AddCompileDefinitions(definesSet, &target, "", linkLanguage);
+    this->AddCompileDefinitions(debugDefinesSet, &target,
+                                "DEBUG", linkLanguage);
+    this->AddCompileDefinitions(releaseDefinesSet, &target,
+                                "RELEASE", linkLanguage);
+    this->AddCompileDefinitions(minsizeDefinesSet, &target,
+                                "MINSIZEREL", linkLanguage);
+    this->AddCompileDefinitions(debugrelDefinesSet, &target,
+                                "RELWITHDEBINFO", linkLanguage);
 
     std::string defines = " ";
     std::string debugDefines = " ";
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index ed560aa..f53f825 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -775,7 +775,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
   cmGeneratorTarget* gt =
     this->GlobalGenerator->GetGeneratorTarget(&target);
   std::vector<std::string> targetDefines;
-  target.GetCompileDefinitions(targetDefines, configName);
+  target.GetCompileDefinitions(targetDefines, configName, "CXX");
   targetOptions.AddDefines(targetDefines);
   targetOptions.SetVerboseMakefile(
     this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 20207f5..57c49f1 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -329,7 +329,7 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
 
     // Add preprocessor definitions for this target and configuration.
     this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
-                            this->LocalGenerator->ConfigurationName);
+                            this->LocalGenerator->ConfigurationName, l);
 
     std::string definesString;
     this->LocalGenerator->JoinDefines(defines, definesString, lang);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index cfd8937..92fccd3 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -231,7 +231,7 @@ ComputeDefines(cmSourceFile const* source, const std::string& language)
 
   // Add preprocessor definitions for this target and configuration.
   this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
-                                             this->GetConfigName());
+                                             this->GetConfigName(), language);
   this->LocalGenerator->AppendDefines
     (defines,
      source->GetProperty("COMPILE_DEFINITIONS"));
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index e18e757..844d708 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -507,7 +507,7 @@ static void GetCompileDefinitionsAndDirectories(cmTarget const* target,
   incs = cmJoin(includeDirs, ";");
 
   std::set<std::string> defines;
-  localGen->AddCompileDefinitions(defines, target, config);
+  localGen->AddCompileDefinitions(defines, target, config, "CXX");
 
   defs += cmJoin(defines, ";");
 }
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index c54d694..87dcc99 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -2336,16 +2336,18 @@ static void processCompileDefinitions(cmTarget const* tgt,
       std::vector<std::string> &options,
       UNORDERED_SET<std::string> &uniqueOptions,
       cmGeneratorExpressionDAGChecker *dagChecker,
-      const std::string& config, bool debugOptions)
+      const std::string& config, bool debugOptions,
+      std::string const& language)
 {
   processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
                                 dagChecker, config, debugOptions,
-                                "definitions", std::string());
+                                "definitions", language);
 }
 
 //----------------------------------------------------------------------------
 void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
-                                            const std::string& config) const
+                                            const std::string& config,
+                                            const std::string& language) const
 {
   UNORDERED_SET<std::string> uniqueOptions;
 
@@ -2377,7 +2379,8 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
                             uniqueOptions,
                             &dagChecker,
                             config,
-                            debugDefines);
+                            debugDefines,
+                            language);
 
   std::vector<cmTargetInternals::TargetPropertyEntry*>
     linkInterfaceCompileDefinitionsEntries;
@@ -2424,7 +2427,8 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
                             uniqueOptions,
                             &dagChecker,
                             config,
-                            debugDefines);
+                            debugDefines,
+                            language);
 
   deleteAndClear(linkInterfaceCompileDefinitionsEntries);
 }
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 56db22e..0356c1e 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -496,7 +496,8 @@ public:
   const char* GetExportMacro() const;
 
   void GetCompileDefinitions(std::vector<std::string> &result,
-                             const std::string& config) const;
+                             const std::string& config,
+                             const std::string& language) const;
 
   // 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 04d1487..19444ed 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1876,7 +1876,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
   clOptions.Parse(flags.c_str());
   clOptions.Parse(defineFlags.c_str());
   std::vector<std::string> targetDefines;
-  this->Target->GetCompileDefinitions(targetDefines, configName.c_str());
+  this->Target->GetCompileDefinitions(targetDefines,
+                                      configName.c_str(), "CXX");
   clOptions.AddDefines(targetDefines);
   if(this->MSTools)
     {
diff --git a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
index 14d40aa..f96283d 100644
--- a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
@@ -26,6 +26,21 @@ target_compile_definitions(consumer
   PRIVATE
 )
 
+if (CMAKE_GENERATOR MATCHES "Makefiles" OR CMAKE_GENERATOR MATCHES "Ninja")
+  target_sources(consumer PRIVATE
+    "${CMAKE_CURRENT_SOURCE_DIR}/consumer.c"
+  )
+  target_compile_definitions(consumer
+    PRIVATE
+      CONSUMER_LANG_$<COMPILE_LANGUAGE>
+      LANG_IS_CXX=$<COMPILE_LANGUAGE:CXX>
+      LANG_IS_C=$<COMPILE_LANGUAGE:C>
+  )
+  target_compile_definitions(consumer
+    PRIVATE -DTEST_LANG_DEFINES
+  )
+endif()
+
 add_definitions(-DSOME_DEF)
 add_library(imp UNKNOWN IMPORTED)
 get_target_property(_res imp COMPILE_DEFINITIONS)
diff --git a/Tests/CMakeCommands/target_compile_definitions/consumer.c b/Tests/CMakeCommands/target_compile_definitions/consumer.c
new file mode 100644
index 0000000..5796d96
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_definitions/consumer.c
@@ -0,0 +1,23 @@
+
+#ifdef TEST_LANG_DEFINES
+  #ifdef CONSUMER_LANG_CXX
+  #error Unexpected CONSUMER_LANG_CXX
+  #endif
+
+  #ifndef CONSUMER_LANG_C
+  #error Expected CONSUMER_LANG_C
+  #endif
+
+  #if !LANG_IS_C
+  #error Expected LANG_IS_C
+  #endif
+
+  #if LANG_IS_CXX
+  #error Unexpected LANG_IS_CXX
+  #endif
+#endif
+
+void consumer_c()
+{
+
+}
diff --git a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp
index a391114..778f57e 100644
--- a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp
+++ b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp
@@ -15,4 +15,22 @@
 #error Expected DASH_D_DEFINE
 #endif
 
+#ifdef TEST_LANG_DEFINES
+  #ifndef CONSUMER_LANG_CXX
+  #error Expected CONSUMER_LANG_CXX
+  #endif
+
+  #ifdef CONSUMER_LANG_C
+  #error Unexpected CONSUMER_LANG_C
+  #endif
+
+  #if !LANG_IS_CXX
+  #error Expected LANG_IS_CXX
+  #endif
+
+  #if LANG_IS_C
+  #error Unexpected LANG_IS_C
+  #endif
+#endif
+
 int main() { return 0; }
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-result.txt b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-stderr-VS.txt b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-stderr-VS.txt
new file mode 100644
index 0000000..73b66ac
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-stderr-VS.txt
@@ -0,0 +1,8 @@
+CMake Error at CompileDefinitions.cmake:5 \(target_compile_definitions\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE:CXX>
+
+  \$<COMPILE_LANGUAGE:...> may not be used with Visual Studio generators.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-stderr-Xcode.txt b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-stderr-Xcode.txt
new file mode 100644
index 0000000..a1ed633
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-stderr-Xcode.txt
@@ -0,0 +1,9 @@
+CMake Error at CompileDefinitions.cmake:5 \(target_compile_definitions\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE:CXX>
+
+  \$<COMPILE_LANGUAGE:...> may only be used with COMPILE_OPTIONS with the
+  Xcode generator.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions.cmake b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions.cmake
new file mode 100644
index 0000000..7935d88
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions.cmake
@@ -0,0 +1,5 @@
+
+enable_language(CXX)
+
+add_executable(main main.cpp)
+target_compile_definitions(main PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-DANYTHING>)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake b/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake
index 2c5d9ae..8a32aef 100644
--- a/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake
@@ -4,3 +4,10 @@ if (RunCMake_GENERATOR MATCHES "Visual Studio")
     set(RunCMake-stderr-file CompileOptions-stderr-VS.txt)
     run_cmake(CompileOptions)
 endif()
+if (RunCMake_GENERATOR STREQUAL "Xcode")
+    set(RunCMake-stderr-file CompileDefinitions-stderr-Xcode.txt)
+    run_cmake(CompileDefinitions)
+elseif (RunCMake_GENERATOR MATCHES "Visual Studio")
+    set(RunCMake-stderr-file CompileDefinitions-stderr-VS.txt)
+    run_cmake(CompileDefinitions)
+endif()

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=89e59bb7837fc98f30ef55e021196125b10faaa4
commit 89e59bb7837fc98f30ef55e021196125b10faaa4
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Nov 25 22:47:44 2014 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Mar 5 20:00:46 2015 +0100

    Genex: Enable use of COMPILE_LANGUAGE for compile options.
    
    Follow-ups will allow the use of the generator expression
    for compile definitions and include directories for non-IDE
    generators.

diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index c47a7c4..b1b1102 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -93,6 +93,32 @@ Available logical expressions are:
   for the 'head' target, an error is reported.  See the
   :manual:`cmake-compile-features(7)` manual for information on
   compile features.
+``$<COMPILE_LANGUAGE:lang>``
+  ``1`` when the language used for compilation unit matches ``lang``,
+  otherwise ``0``.  This expression used to specify compile options for
+  source files of a particular language in a target. For example, to specify
+  the use of the ``-fno-exceptions`` compile option (compiler id checks
+  elided):
+
+  .. code-block:: cmake
+
+    add_executable(myapp main.cpp foo.c bar.cpp)
+    target_compile_options(myapp
+      PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
+    )
+
+  This generator expression has limited use because it is not possible to
+  use it with the Visual Studio generators.  Portable buildsystems would
+  not use this expression, and would create separate libraries for each
+  source file language instead:
+
+  .. code-block:: cmake
+
+    add_library(myapp_c foo.c)
+    add_library(myapp_cxx foo.c)
+    target_compile_options(myapp_cxx PUBLIC -fno-exceptions)
+    add_executable(myapp main.cpp)
+    target_link_libraries(myapp myapp_c myapp_cxx)
 
 Informational Expressions
 =========================
@@ -174,6 +200,10 @@ Available informational expressions are:
 ``$<INSTALL_PREFIX>``
   Content of the install prefix when the target is exported via
   :command:`install(EXPORT)` and empty otherwise.
+``$<COMPILE_LANGUAGE>``
+  The compile language of source files when evaluating compile options. See
+  the unary version for notes about portability of this generator
+  expression.
 
 Output Expressions
 ==================
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 63a46f2..89bdb5b 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -827,6 +827,38 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
           "components of the file(GENERATE) command.");
       return std::string();
       }
+
+    std::vector<std::string> enabledLanguages;
+    cmGlobalGenerator* gg
+        = context->Makefile->GetLocalGenerator()->GetGlobalGenerator();
+    gg->GetEnabledLanguages(enabledLanguages);
+    if (!parameters.empty() &&
+          std::find(enabledLanguages.begin(), enabledLanguages.end(),
+                  parameters.front()) == enabledLanguages.end())
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<COMPILE_LANGUAGE:...> Unknown language.");
+      return std::string();
+      }
+
+    if (gg->GetName().find("Visual Studio") != std::string::npos)
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<COMPILE_LANGUAGE:...> may not be used with Visual Studio "
+          "generators.");
+      return std::string();
+      }
+    else
+      {
+      if(gg->GetName().find("Makefiles") == std::string::npos &&
+              gg->GetName().find("Ninja") == std::string::npos &&
+              gg->GetName().find("Xcode") == std::string::npos)
+        {
+        reportError(context, content->GetOriginalExpression(),
+            "$<COMPILE_LANGUAGE:...> not supported for this generator.");
+        return std::string();
+        }
+      }
     if (parameters.empty())
       {
       return context->Language;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 7c83f27..be82085 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1453,7 +1453,7 @@ void cmLocalGenerator::AddCompileOptions(
       {
       cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
       }
-    target->GetCompileOptions(opts, config);
+    target->GetCompileOptions(opts, config, lang);
     for(std::vector<std::string>::const_iterator i = opts.begin();
         i != opts.end(); ++i)
       {
@@ -1474,7 +1474,7 @@ void cmLocalGenerator::AddCompileOptions(
       this->AppendFlags(flags, targetFlags);
       }
     std::vector<std::string> opts;
-    target->GetCompileOptions(opts, config);
+    target->GetCompileOptions(opts, config, lang);
     for(std::vector<std::string>::const_iterator i = opts.begin();
         i != opts.end(); ++i)
       {
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index e046bef..c54d694 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -2192,7 +2192,8 @@ static void processCompileOptionsInternal(cmTarget const* tgt,
       std::vector<std::string> &options,
       UNORDERED_SET<std::string> &uniqueOptions,
       cmGeneratorExpressionDAGChecker *dagChecker,
-      const std::string& config, bool debugOptions, const char *logName)
+      const std::string& config, bool debugOptions, const char *logName,
+      std::string const& language)
 {
   cmMakefile *mf = tgt->GetMakefile();
 
@@ -2204,7 +2205,8 @@ static void processCompileOptionsInternal(cmTarget const* tgt,
                                               config,
                                               false,
                                               tgt,
-                                              dagChecker),
+                                              dagChecker,
+                                              language),
                                     entryOptions);
     std::string usedOptions;
     for(std::vector<std::string>::iterator
@@ -2238,10 +2240,12 @@ static void processCompileOptions(cmTarget const* tgt,
       std::vector<std::string> &options,
       UNORDERED_SET<std::string> &uniqueOptions,
       cmGeneratorExpressionDAGChecker *dagChecker,
-      const std::string& config, bool debugOptions)
+      const std::string& config, bool debugOptions,
+      std::string const& language)
 {
   processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
-                                dagChecker, config, debugOptions, "options");
+                                dagChecker, config, debugOptions, "options",
+                                language);
 }
 
 //----------------------------------------------------------------------------
@@ -2271,7 +2275,8 @@ void cmTarget::GetAutoUicOptions(std::vector<std::string> &result,
 
 //----------------------------------------------------------------------------
 void cmTarget::GetCompileOptions(std::vector<std::string> &result,
-                                 const std::string& config) const
+                                 const std::string& config,
+                                 const std::string& language) const
 {
   UNORDERED_SET<std::string> uniqueOptions;
 
@@ -2303,7 +2308,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
                             uniqueOptions,
                             &dagChecker,
                             config,
-                            debugOptions);
+                            debugOptions,
+                            language);
 
   std::vector<cmTargetInternals::TargetPropertyEntry*>
     linkInterfaceCompileOptionsEntries;
@@ -2318,7 +2324,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
                             uniqueOptions,
                             &dagChecker,
                             config,
-                            debugOptions);
+                            debugOptions,
+                            language);
 
   deleteAndClear(linkInterfaceCompileOptionsEntries);
 }
@@ -2333,7 +2340,7 @@ static void processCompileDefinitions(cmTarget const* tgt,
 {
   processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
                                 dagChecker, config, debugOptions,
-                                "definitions");
+                                "definitions", std::string());
 }
 
 //----------------------------------------------------------------------------
@@ -2431,7 +2438,8 @@ static void processCompileFeatures(cmTarget const* tgt,
       const std::string& config, bool debugOptions)
 {
   processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
-                                dagChecker, config, debugOptions, "features");
+                                dagChecker, config, debugOptions, "features",
+                                std::string());
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index ddd9859..56db22e 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -577,7 +577,8 @@ public:
   void AppendBuildInterfaceIncludes();
 
   void GetCompileOptions(std::vector<std::string> &result,
-                         const std::string& config) const;
+                         const std::string& config,
+                         const std::string& language) const;
   void GetAutoUicOptions(std::vector<std::string> &result,
                          const std::string& config) const;
   void GetCompileFeatures(std::vector<std::string> &features,
diff --git a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
index 1d04639..35dd276 100644
--- a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
@@ -23,6 +23,21 @@ add_executable(consumer
   "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
 )
 
+if (NOT CMAKE_GENERATOR MATCHES "Visual Studio")
+  target_sources(consumer PRIVATE
+    "${CMAKE_CURRENT_SOURCE_DIR}/consumer.c"
+  )
+  target_compile_options(consumer
+    PRIVATE
+      -DCONSUMER_LANG_$<COMPILE_LANGUAGE>
+      -DLANG_IS_CXX=$<COMPILE_LANGUAGE:CXX>
+      -DLANG_IS_C=$<COMPILE_LANGUAGE:C>
+  )
+  target_compile_definitions(consumer
+    PRIVATE -DTEST_LANG_DEFINES
+  )
+endif()
+
 target_compile_options(consumer
   PRIVATE $<$<CXX_COMPILER_ID:GNU>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>>
 )
diff --git a/Tests/CMakeCommands/target_compile_options/consumer.c b/Tests/CMakeCommands/target_compile_options/consumer.c
new file mode 100644
index 0000000..5796d96
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_options/consumer.c
@@ -0,0 +1,23 @@
+
+#ifdef TEST_LANG_DEFINES
+  #ifdef CONSUMER_LANG_CXX
+  #error Unexpected CONSUMER_LANG_CXX
+  #endif
+
+  #ifndef CONSUMER_LANG_C
+  #error Expected CONSUMER_LANG_C
+  #endif
+
+  #if !LANG_IS_C
+  #error Expected LANG_IS_C
+  #endif
+
+  #if LANG_IS_CXX
+  #error Unexpected LANG_IS_CXX
+  #endif
+#endif
+
+void consumer_c()
+{
+
+}
diff --git a/Tests/CMakeCommands/target_compile_options/consumer.cpp b/Tests/CMakeCommands/target_compile_options/consumer.cpp
index 1299606..c5882a5 100644
--- a/Tests/CMakeCommands/target_compile_options/consumer.cpp
+++ b/Tests/CMakeCommands/target_compile_options/consumer.cpp
@@ -15,4 +15,22 @@
 
 #endif
 
+#ifdef TEST_LANG_DEFINES
+  #ifndef CONSUMER_LANG_CXX
+  #error Expected CONSUMER_LANG_CXX
+  #endif
+
+  #ifdef CONSUMER_LANG_C
+  #error Unexpected CONSUMER_LANG_C
+  #endif
+
+  #if !LANG_IS_CXX
+  #error Expected LANG_IS_CXX
+  #endif
+
+  #if LANG_IS_C
+  #error Unexpected LANG_IS_C
+  #endif
+#endif
+
 int main() { return 0; }
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index eb42057..9f1256e 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -208,3 +208,5 @@ add_RunCMake_test(IfacePaths_SOURCES TEST_DIR IfacePaths)
 if(RPMBUILD_EXECUTABLE)
   add_RunCMake_test(CPackRPM)
 endif()
+
+add_RunCMake_test(COMPILE_LANGUAGE-genex)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/CMakeLists.txt b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CMakeLists.txt
new file mode 100644
index 0000000..ef2163c
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.1)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions-result.txt b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions-stderr-VS.txt b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions-stderr-VS.txt
new file mode 100644
index 0000000..e9e8e9f
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions-stderr-VS.txt
@@ -0,0 +1,8 @@
+CMake Error at CompileOptions.cmake:5 \(target_compile_options\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE:CXX>
+
+  \$<COMPILE_LANGUAGE:...> may not be used with Visual Studio generators.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions.cmake b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions.cmake
new file mode 100644
index 0000000..6c92abc
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions.cmake
@@ -0,0 +1,5 @@
+
+enable_language(CXX)
+
+add_executable(main main.cpp)
+target_compile_options(main PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-DANYTHING>)
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake b/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake
new file mode 100644
index 0000000..2c5d9ae
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake
@@ -0,0 +1,6 @@
+include(RunCMake)
+
+if (RunCMake_GENERATOR MATCHES "Visual Studio")
+    set(RunCMake-stderr-file CompileOptions-stderr-VS.txt)
+    run_cmake(CompileOptions)
+endif()
diff --git a/Tests/RunCMake/COMPILE_LANGUAGE-genex/main.cpp b/Tests/RunCMake/COMPILE_LANGUAGE-genex/main.cpp
new file mode 100644
index 0000000..31a1337
--- /dev/null
+++ b/Tests/RunCMake/COMPILE_LANGUAGE-genex/main.cpp
@@ -0,0 +1,5 @@
+
+int main()
+{
+    return 0;
+}
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-result.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-stderr.txt
new file mode 100644
index 0000000..444da45
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at COMPILE_LANGUAGE-unknown-lang.cmake:4 \(target_compile_options\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE:CXX>
+
+  \$<COMPILE_LANGUAGE:...> Unknown language.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang.cmake
new file mode 100644
index 0000000..cec12a3
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang.cmake
@@ -0,0 +1,4 @@
+
+enable_language(C)
+add_executable(empty empty.c)
+target_compile_options(empty PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wall>)
diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
index f591c3d..542b7fc 100644
--- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
@@ -23,6 +23,7 @@ run_cmake(COMPILE_LANGUAGE-target_sources)
 run_cmake(COMPILE_LANGUAGE-add_executable)
 run_cmake(COMPILE_LANGUAGE-add_library)
 run_cmake(COMPILE_LANGUAGE-add_test)
+run_cmake(COMPILE_LANGUAGE-unknown-lang)
 
 if(LINKER_SUPPORTS_PDB)
   run_cmake(NonValidTarget-TARGET_PDB_FILE)

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

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list