浏览代码

Merge topic 'target-language-genex'

232a6883 Help: Add release notes for target-language-genex.
9e168941 File(GENERATE): Process genex evaluation files for each language.
b734fa44 Genex: Allow COMPILE_LANGUAGE when processing include directories.
0b945ea9 Genex: Allow COMPILE_LANGUAGE when processing compile definitions.
5c559f11 Genex: Enable use of COMPILE_LANGUAGE for compile options.
e387ce7d Genex: Add a COMPILE_LANGUAGE generator expression.
4a0128f4 VS6: Compute CMAKE_*_FLAGS and COMPILE_DEFINITIONS* only when needed
Brad King 10 年之前
父节点
当前提交
ad6fbb88bb
共有 80 个文件被更改,包括 756 次插入177 次删除
  1. 44 0
      Help/manual/cmake-generator-expressions.7.rst
  2. 9 0
      Help/release/dev/target-language-genex.rst
  3. 1 1
      Source/cmExtraCodeBlocksGenerator.cxx
  4. 1 1
      Source/cmExtraSublimeTextGenerator.cxx
  5. 7 3
      Source/cmGeneratorExpression.cxx
  6. 4 2
      Source/cmGeneratorExpression.h
  7. 37 14
      Source/cmGeneratorExpressionEvaluationFile.cxx
  8. 1 1
      Source/cmGeneratorExpressionEvaluationFile.h
  9. 75 1
      Source/cmGeneratorExpressionEvaluator.cxx
  10. 1 0
      Source/cmGeneratorExpressionEvaluator.h
  11. 3 2
      Source/cmGeneratorTarget.cxx
  12. 1 1
      Source/cmGeneratorTarget.h
  13. 1 1
      Source/cmGlobalXCodeGenerator.cxx
  14. 6 6
      Source/cmLocalGenerator.cxx
  15. 2 1
      Source/cmLocalGenerator.h
  16. 38 12
      Source/cmLocalUnixMakefileGenerator3.cxx
  17. 75 70
      Source/cmLocalVisualStudio6Generator.cxx
  18. 1 1
      Source/cmLocalVisualStudio7Generator.cxx
  19. 1 35
      Source/cmMakefileTargetGenerator.cxx
  20. 1 1
      Source/cmNinjaTargetGenerator.cxx
  21. 1 1
      Source/cmQtAutoGenerators.cxx
  22. 34 18
      Source/cmTarget.cxx
  23. 6 3
      Source/cmTarget.h
  24. 2 1
      Source/cmVisualStudio10TargetGenerator.cxx
  25. 15 0
      Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
  26. 23 0
      Tests/CMakeCommands/target_compile_definitions/consumer.c
  27. 18 0
      Tests/CMakeCommands/target_compile_definitions/consumer.cpp
  28. 15 0
      Tests/CMakeCommands/target_compile_options/CMakeLists.txt
  29. 23 0
      Tests/CMakeCommands/target_compile_options/consumer.c
  30. 18 0
      Tests/CMakeCommands/target_compile_options/consumer.cpp
  31. 14 0
      Tests/CMakeCommands/target_include_directories/CMakeLists.txt
  32. 2 0
      Tests/CMakeCommands/target_include_directories/c_only/c_only.h
  33. 10 0
      Tests/CMakeCommands/target_include_directories/consumer.c
  34. 9 0
      Tests/CMakeCommands/target_include_directories/consumer.cpp
  35. 2 0
      Tests/CMakeCommands/target_include_directories/cxx_only/cxx_only.h
  36. 2 0
      Tests/RunCMake/CMakeLists.txt
  37. 3 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/CMakeLists.txt
  38. 1 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-result.txt
  39. 8 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-stderr-VS.txt
  40. 9 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-stderr-Xcode.txt
  41. 5 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions.cmake
  42. 1 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions-result.txt
  43. 8 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions-stderr-VS.txt
  44. 5 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions.cmake
  45. 1 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-result.txt
  46. 8 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-stderr-VS.txt
  47. 9 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-stderr-Xcode.txt
  48. 5 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories.cmake
  49. 20 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake
  50. 5 0
      Tests/RunCMake/COMPILE_LANGUAGE-genex/main.cpp
  51. 1 0
      Tests/RunCMake/File_Generate/COMPILE_LANGUAGE-genex-result.txt
  52. 12 0
      Tests/RunCMake/File_Generate/COMPILE_LANGUAGE-genex.cmake
  53. 1 1
      Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
  54. 10 0
      Tests/RunCMake/File_Generate/RunCMakeTest.cmake
  55. 8 0
      Tests/RunCMake/File_Generate/empty.c
  56. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command-result.txt
  57. 10 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command-stderr.txt
  58. 8 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command.cmake
  59. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target-result.txt
  60. 10 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target-stderr.txt
  61. 6 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target.cmake
  62. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable-result.txt
  63. 10 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable-stderr.txt
  64. 4 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable.cmake
  65. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library-result.txt
  66. 10 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library-stderr.txt
  67. 4 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library.cmake
  68. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_test-result.txt
  69. 10 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_test-stderr.txt
  70. 5 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_test.cmake
  71. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-install-result.txt
  72. 8 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-install-stderr.txt
  73. 5 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-install.cmake
  74. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources-result.txt
  75. 10 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources-stderr.txt
  76. 5 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources.cmake
  77. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-result.txt
  78. 8 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-stderr.txt
  79. 4 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang.cmake
  80. 8 0
      Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake

+ 44 - 0
Help/manual/cmake-generator-expressions.7.rst

@@ -93,6 +93,46 @@ 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)
+
+  The ``Makefile`` and ``Ninja`` based generators can also use this
+  expression to specify compile-language specific compile definitions
+  and include directories:
+
+  .. code-block:: cmake
+
+    add_executable(myapp main.cpp foo.c bar.cpp)
+    target_compile_definitions(myapp
+      PRIVATE $<$<COMPILE_LANGUAGE:CXX>:COMPILING_CXX>
+    )
+    target_include_directories(myapp
+      PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/opt/foo/cxx_headers>
+    )
 
 Informational Expressions
 =========================
@@ -174,6 +214,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
 ==================

+ 9 - 0
Help/release/dev/target-language-genex.rst

@@ -0,0 +1,9 @@
+target-language-genex
+---------------------
+
+* A new ``COMPILE_LANGUAGE`` generator expression was introduced to
+  allow specification of compile options for target files based on the
+  :prop_sf:`LANGUAGE` of each source file.  Due to limitations of the
+  underlying native build tools, this feature has varying support across
+  generators.  See the :manual:`cmake-generator-expressions(7)` manual
+  for details.

+ 1 - 1
Source/cmExtraCodeBlocksGenerator.cxx

@@ -604,7 +604,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();

+ 1 - 1
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_";

+ 7 - 3
Source/cmGeneratorExpression.cxx

@@ -52,14 +52,16 @@ cmGeneratorExpression::~cmGeneratorExpression()
 const char *cmCompiledGeneratorExpression::Evaluate(
   cmMakefile* mf, const std::string& config, bool quiet,
   cmTarget const* headTarget,
-  cmGeneratorExpressionDAGChecker *dagChecker) const
+  cmGeneratorExpressionDAGChecker *dagChecker,
+                       std::string const& language) const
 {
   return this->Evaluate(mf,
                         config,
                         quiet,
                         headTarget,
                         headTarget,
-                        dagChecker);
+                        dagChecker,
+                        language);
 }
 
 //----------------------------------------------------------------------------
@@ -67,7 +69,8 @@ const char *cmCompiledGeneratorExpression::Evaluate(
   cmMakefile* mf, const std::string& config, bool quiet,
   cmTarget const* headTarget,
   cmTarget const* currentTarget,
-  cmGeneratorExpressionDAGChecker *dagChecker) const
+  cmGeneratorExpressionDAGChecker *dagChecker,
+  std::string const& language) const
 {
   if (!this->NeedsEvaluation)
     {
@@ -93,6 +96,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
   context.EvaluateForBuildsystem = this->EvaluateForBuildsystem;
   context.CurrentTarget = currentTarget ? currentTarget : headTarget;
   context.Backtrace = this->Backtrace;
+  context.Language = language;
 
   for ( ; it != end; ++it)
     {

+ 4 - 2
Source/cmGeneratorExpression.h

@@ -80,11 +80,13 @@ public:
                        bool quiet = false,
                        cmTarget const* headTarget = 0,
                        cmTarget const* currentTarget = 0,
-                       cmGeneratorExpressionDAGChecker *dagChecker = 0) const;
+                       cmGeneratorExpressionDAGChecker *dagChecker = 0,
+                       std::string const& language = std::string()) const;
   const char* Evaluate(cmMakefile* mf, const std::string& config,
                        bool quiet,
                        cmTarget const* headTarget,
-                       cmGeneratorExpressionDAGChecker *dagChecker) const;
+                       cmGeneratorExpressionDAGChecker *dagChecker,
+                       std::string const& language = std::string()) const;
 
   /** Get set of targets found during evaluations.  */
   std::set<cmTarget*> const& GetTargets() const

+ 37 - 14
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;
+        }
       }
     }
 }

+ 1 - 1
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);
 

+ 75 - 1
Source/cmGeneratorExpressionEvaluator.cxx

@@ -16,6 +16,7 @@
 #include "cmGeneratorExpressionDAGChecker.h"
 #include "cmGeneratorExpression.h"
 #include "cmLocalGenerator.h"
+#include "cmGlobalGenerator.h"
 #include "cmSourceFile.h"
 
 #include <cmsys/String.h>
@@ -89,7 +90,8 @@ std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
                         context->Quiet,
                         headTarget,
                         currentTarget,
-                        dagChecker);
+                        dagChecker,
+                        context->Language);
   if (cge->GetHadContextSensitiveCondition())
     {
     context->HadContextSensitiveCondition = true;
@@ -806,6 +808,77 @@ static const struct JoinNode : public cmGeneratorExpressionNode
   }
 } joinNode;
 
+static const struct CompileLanguageNode : public cmGeneratorExpressionNode
+{
+  CompileLanguageNode() {}
+
+  virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *context,
+                       const GeneratorExpressionContent *content,
+                       cmGeneratorExpressionDAGChecker *dagChecker) const
+  {
+    if(context->Language.empty())
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<COMPILE_LANGUAGE:...> may only be used to specify include "
+          "directories compile definitions, compile options and to evaluate "
+          "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();
+      }
+
+    std::string genName = gg->GetName();
+    if (genName.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 (genName.find("Xcode") != std::string::npos)
+      {
+      if (dagChecker && (dagChecker->EvaluatingCompileDefinitions()
+          || dagChecker->EvaluatingIncludeDirectories()))
+        {
+        reportError(context, content->GetOriginalExpression(),
+            "$<COMPILE_LANGUAGE:...> may only be used with COMPILE_OPTIONS "
+            "with the Xcode generator.");
+        return std::string();
+        }
+      }
+    else
+      {
+      if(genName.find("Makefiles") == std::string::npos &&
+              genName.find("Ninja") == std::string::npos &&
+              genName.find("Watcom WMake") == std::string::npos)
+        {
+        reportError(context, content->GetOriginalExpression(),
+            "$<COMPILE_LANGUAGE:...> not supported for this generator.");
+        return std::string();
+        }
+      }
+    if (parameters.empty())
+      {
+      return context->Language;
+      }
+    return context->Language == parameters.front() ? "1" : "0";
+  }
+} languageNode;
+
 #define TRANSITIVE_PROPERTY_NAME(PROPERTY) \
   , "INTERFACE_" #PROPERTY
 
@@ -1829,6 +1902,7 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
     nodeMap["JOIN"] = &joinNode;
     nodeMap["LINK_ONLY"] = &linkOnlyNode;
+    nodeMap["COMPILE_LANGUAGE"] = &languageNode;
     }
   NodeMap::const_iterator i = nodeMap.find(identifier);
   if (i == nodeMap.end())

+ 1 - 0
Source/cmGeneratorExpressionEvaluator.h

@@ -36,6 +36,7 @@ struct cmGeneratorExpressionContext
                                                           MaxLanguageStandard;
   cmMakefile *Makefile;
   std::string Config;
+  std::string Language;
   cmTarget const* HeadTarget; // The target whose property is being evaluated.
   cmTarget const* CurrentTarget; // The dependent of HeadTarget which appears
                                  // directly or indirectly in the property.

+ 3 - 2
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);
 }
 
 //----------------------------------------------------------------------------

+ 1 - 1
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;

+ 1 - 1
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());

+ 6 - 6
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);
 }
 
@@ -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)
       {
@@ -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.

+ 2 - 1
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);

+ 38 - 12
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -2042,23 +2042,49 @@ 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())
-    {
+    // 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
+        << "\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";
+      }
+
+    // Target-specific include directories:
     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)
+      << "# 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->EscapeForCMake(*di) << "\n";
+        << "  \""
+        << this->Convert(*i, cmLocalGenerator::HOME_OUTPUT)
+        << "\"\n";
       }
     cmakefileStream
       << "  )\n";

+ 75 - 70
Source/cmLocalVisualStudio6Generator.cxx

@@ -1701,15 +1701,15 @@ void cmLocalVisualStudio6Generator
       = this->Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
     cmSystemTools::ReplaceString(line, "DEBUG_POSTFIX",
                                  debugPostfix?debugPostfix:"");
-    // store flags for each configuration
-    std::string flags = " ";
-    std::string flagsRelease = " ";
-    std::string flagsMinSizeRel = " ";
-    std::string flagsDebug = " ";
-    std::string flagsRelWithDebInfo = " ";
     if(target.GetType() >= cmTarget::EXECUTABLE &&
        target.GetType() <= cmTarget::OBJECT_LIBRARY)
       {
+      // store flags for each configuration
+      std::string flags = " ";
+      std::string flagsRelease = " ";
+      std::string flagsMinSizeRel = " ";
+      std::string flagsDebug = " ";
+      std::string flagsRelWithDebInfo = " ";
       std::vector<std::string> configs;
       target.GetMakefile()->GetConfigurations(configs);
       std::vector<std::string>::const_iterator it = configs.begin();
@@ -1760,72 +1760,77 @@ void cmLocalVisualStudio6Generator
                               "MinSizeRel");
       this->AddCompileOptions(flagsRelWithDebInfo, &target, linkLanguage,
                               "RelWithDebInfo");
-      }
 
-    // if _UNICODE and _SBCS are not found, then add -D_MBCS
-    std::string defs = this->Makefile->GetDefineFlags();
-    if(flags.find("D_UNICODE") == flags.npos &&
-       defs.find("D_UNICODE") == flags.npos &&
-       flags.find("D_SBCS") == flags.npos &&
-       defs.find("D_SBCS") == flags.npos)
-      {
-      flags += " /D \"_MBCS\"";
-      }
+      // if _UNICODE and _SBCS are not found, then add -D_MBCS
+      std::string defs = this->Makefile->GetDefineFlags();
+      if(flags.find("D_UNICODE") == flags.npos &&
+         defs.find("D_UNICODE") == flags.npos &&
+         flags.find("D_SBCS") == flags.npos &&
+         defs.find("D_SBCS") == flags.npos)
+        {
+        flags += " /D \"_MBCS\"";
+        }
 
-    // Add per-target and per-configuration preprocessor definitions.
-    std::set<std::string> definesSet;
-    std::set<std::string> debugDefinesSet;
-    std::set<std::string> releaseDefinesSet;
-    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");
-
-    std::string defines = " ";
-    std::string debugDefines = " ";
-    std::string releaseDefines = " ";
-    std::string minsizeDefines = " ";
-    std::string debugrelDefines = " ";
-
-    this->JoinDefines(definesSet, defines, "");
-    this->JoinDefines(debugDefinesSet, debugDefines, "");
-    this->JoinDefines(releaseDefinesSet, releaseDefines, "");
-    this->JoinDefines(minsizeDefinesSet, minsizeDefines, "");
-    this->JoinDefines(debugrelDefinesSet, debugrelDefines, "");
-
-    flags += defines;
-    flagsDebug += debugDefines;
-    flagsRelease += releaseDefines;
-    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",
-                                 flagsMinSizeRel.c_str());
-    cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG",
-                                 flagsDebug.c_str());
-    cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
-                                 flagsRelWithDebInfo.c_str());
-    cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE",
-                                 flagsRelease.c_str());
-    cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
-
-    cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_MINSIZEREL",
-                                 minsizeDefines.c_str());
-    cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_DEBUG",
-                                 debugDefines.c_str());
-    cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELWITHDEBINFO",
-                                 debugrelDefines.c_str());
-    cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELEASE",
-                                 releaseDefines.c_str());
-    cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS", defines.c_str());
+      // Add per-target and per-configuration preprocessor definitions.
+      std::set<std::string> definesSet;
+      std::set<std::string> debugDefinesSet;
+      std::set<std::string> releaseDefinesSet;
+      std::set<std::string> minsizeDefinesSet;
+      std::set<std::string> debugrelDefinesSet;
+
+      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 = " ";
+      std::string releaseDefines = " ";
+      std::string minsizeDefines = " ";
+      std::string debugrelDefines = " ";
+
+      this->JoinDefines(definesSet, defines, "");
+      this->JoinDefines(debugDefinesSet, debugDefines, "");
+      this->JoinDefines(releaseDefinesSet, releaseDefines, "");
+      this->JoinDefines(minsizeDefinesSet, minsizeDefines, "");
+      this->JoinDefines(debugrelDefinesSet, debugrelDefines, "");
+
+      flags += defines;
+      flagsDebug += debugDefines;
+      flagsRelease += releaseDefines;
+      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",
+                                   flagsMinSizeRel.c_str());
+      cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG",
+                                   flagsDebug.c_str());
+      cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
+                                   flagsRelWithDebInfo.c_str());
+      cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE",
+                                   flagsRelease.c_str());
+      cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
+
+      cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_MINSIZEREL",
+                                   minsizeDefines.c_str());
+      cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_DEBUG",
+                                   debugDefines.c_str());
+      cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELWITHDEBINFO",
+                                   debugrelDefines.c_str());
+      cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELEASE",
+                                   releaseDefines.c_str());
+      cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS",
+                                   defines.c_str());
+      }
 
     fout << line.c_str() << std::endl;
     }

+ 1 - 1
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"));

+ 1 - 35
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);
@@ -1126,40 +1126,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;

+ 1 - 1
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"));

+ 1 - 1
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, ";");
 }

+ 34 - 18
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);
 
@@ -2192,7 +2196,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 +2209,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 +2244,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 +2279,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 +2312,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
                             uniqueOptions,
                             &dagChecker,
                             config,
-                            debugOptions);
+                            debugOptions,
+                            language);
 
   std::vector<cmTargetInternals::TargetPropertyEntry*>
     linkInterfaceCompileOptionsEntries;
@@ -2318,7 +2328,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
                             uniqueOptions,
                             &dagChecker,
                             config,
-                            debugOptions);
+                            debugOptions,
+                            language);
 
   deleteAndClear(linkInterfaceCompileOptionsEntries);
 }
@@ -2329,16 +2340,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");
+                                "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;
 
@@ -2370,7 +2383,8 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
                             uniqueOptions,
                             &dagChecker,
                             config,
-                            debugDefines);
+                            debugDefines,
+                            language);
 
   std::vector<cmTargetInternals::TargetPropertyEntry*>
     linkInterfaceCompileDefinitionsEntries;
@@ -2417,7 +2431,8 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
                             uniqueOptions,
                             &dagChecker,
                             config,
-                            debugDefines);
+                            debugDefines,
+                            language);
 
   deleteAndClear(linkInterfaceCompileDefinitionsEntries);
 }
@@ -2431,7 +2446,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());
 }
 
 //----------------------------------------------------------------------------

+ 6 - 3
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
@@ -567,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,
@@ -577,7 +579,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,

+ 2 - 1
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)
     {

+ 15 - 0
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)

+ 23 - 0
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()
+{
+
+}

+ 18 - 0
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; }

+ 15 - 0
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>>
 )

+ 23 - 0
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()
+{
+
+}

+ 18 - 0
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; }

+ 14 - 0
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>

+ 2 - 0
Tests/CMakeCommands/target_include_directories/c_only/c_only.h

@@ -0,0 +1,2 @@
+
+#define C_ONLY_DEFINE

+ 10 - 0
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; }

+ 9 - 0
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; }

+ 2 - 0
Tests/CMakeCommands/target_include_directories/cxx_only/cxx_only.h

@@ -0,0 +1,2 @@
+
+#define CXX_ONLY_DEFINE

+ 2 - 0
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)

+ 3 - 0
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)

+ 1 - 0
Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileDefinitions-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
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\)

+ 9 - 0
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\)

+ 5 - 0
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>)

+ 1 - 0
Tests/RunCMake/COMPILE_LANGUAGE-genex/CompileOptions-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
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\)

+ 5 - 0
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>)

+ 1 - 0
Tests/RunCMake/COMPILE_LANGUAGE-genex/IncludeDirectories-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
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\)

+ 9 - 0
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\)

+ 5 - 0
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>)

+ 20 - 0
Tests/RunCMake/COMPILE_LANGUAGE-genex/RunCMakeTest.cmake

@@ -0,0 +1,20 @@
+include(RunCMake)
+
+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()
+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()

+ 5 - 0
Tests/RunCMake/COMPILE_LANGUAGE-genex/main.cpp

@@ -0,0 +1,5 @@
+
+int main()
+{
+    return 0;
+}

+ 1 - 0
Tests/RunCMake/File_Generate/COMPILE_LANGUAGE-genex-result.txt

@@ -0,0 +1 @@
+0

+ 12 - 0
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"
+)

+ 1 - 1
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

+ 10 - 0
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")

+ 8 - 0
Tests/RunCMake/File_Generate/empty.c

@@ -0,0 +1,8 @@
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty_c()
+{
+  return 0;
+}

+ 1 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at COMPILE_LANGUAGE-add_custom_command.cmake:6 \(add_custom_command\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE>
+
+  \$<COMPILE_LANGUAGE:...> may only be used to specify include directories
+  compile definitions, compile options and to evaluate components of the
+  file\(GENERATE\) command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 8 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command.cmake

@@ -0,0 +1,8 @@
+
+enable_language(C)
+
+add_library(empty empty.c)
+
+add_custom_command(TARGET empty PRE_BUILD
+  COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANGUAGE>
+)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at COMPILE_LANGUAGE-add_custom_target.cmake:4 \(add_custom_target\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE>
+
+  \$<COMPILE_LANGUAGE:...> may only be used to specify include directories
+  compile definitions, compile options and to evaluate components of the
+  file\(GENERATE\) command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 6 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target.cmake

@@ -0,0 +1,6 @@
+
+enable_language(C)
+
+add_custom_target(empty
+  COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANGUAGE>
+)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at COMPILE_LANGUAGE-add_executable.cmake:4 \(add_executable\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE>
+
+  \$<COMPILE_LANGUAGE:...> may only be used to specify include directories
+  compile definitions, compile options and to evaluate components of the
+  file\(GENERATE\) command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 4 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable.cmake

@@ -0,0 +1,4 @@
+
+enable_language(C)
+
+add_executable(empty empty.$<COMPILE_LANGUAGE>)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at COMPILE_LANGUAGE-add_library.cmake:4 \(add_library\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE>
+
+  \$<COMPILE_LANGUAGE:...> may only be used to specify include directories
+  compile definitions, compile options and to evaluate components of the
+  file\(GENERATE\) command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 4 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library.cmake

@@ -0,0 +1,4 @@
+
+enable_language(C)
+
+add_library(empty empty.$<COMPILE_LANGUAGE>)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_test-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_test-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at COMPILE_LANGUAGE-add_test.cmake:5 \(add_test\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE>
+
+  \$<COMPILE_LANGUAGE:...> may only be used to specify include directories
+  compile definitions, compile options and to evaluate components of the
+  file\(GENERATE\) command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 5 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_test.cmake

@@ -0,0 +1,5 @@
+
+include(CTest)
+enable_testing()
+
+add_test(NAME dummy COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANGUAGE>)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-install-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-install-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE>
+
+  \$<COMPILE_LANGUAGE:...> may only be used to specify include directories
+  compile definitions, compile options and to evaluate components of the
+  file\(GENERATE\) command.

+ 5 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-install.cmake

@@ -0,0 +1,5 @@
+
+install(FILES
+  empty.$<COMPILE_LANGUAGE>
+  DESTINATION src
+)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at COMPILE_LANGUAGE-target_sources.cmake:5 \(target_sources\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANGUAGE>
+
+  \$<COMPILE_LANGUAGE:...> may only be used to specify include directories
+  compile definitions, compile options and to evaluate components of the
+  file\(GENERATE\) command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 5 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources.cmake

@@ -0,0 +1,5 @@
+
+enable_language(C)
+
+add_library(empty empty.c)
+target_sources(empty PRIVATE empty.$<COMPILE_LANGUAGE>)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
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\)

+ 4 - 0
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>)

+ 8 - 0
Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake

@@ -16,6 +16,14 @@ run_cmake(NonValidTarget-C_COMPILER_VERSION)
 run_cmake(NonValidTarget-CXX_COMPILER_VERSION)
 run_cmake(NonValidTarget-TARGET_PROPERTY)
 run_cmake(NonValidTarget-TARGET_POLICY)
+run_cmake(COMPILE_LANGUAGE-add_custom_target)
+run_cmake(COMPILE_LANGUAGE-add_custom_command)
+run_cmake(COMPILE_LANGUAGE-install)
+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)