Browse Source

Genex: Allow COMPILE_LANGUAGE when processing compile definitions.

Issue an error if this is encountered by an IDE generator.
Stephen Kelly 10 years ago
parent
commit
0b945ea9a6

+ 10 - 0
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
 =========================
 

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

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

+ 12 - 3
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())
       {
@@ -849,12 +849,21 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
           "generators.");
       return std::string();
       }
+    else if (genName.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(genName.find("Makefiles") == std::string::npos &&
               genName.find("Ninja") == std::string::npos &&
-              genName.find("Watcom WMake") == std::string::npos &&
-              genName.find("Xcode") == std::string::npos)
+              genName.find("Watcom WMake") == std::string::npos)
         {
         reportError(context, content->GetOriginalExpression(),
             "$<COMPILE_LANGUAGE:...> not supported for this generator.");

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

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

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

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

+ 5 - 5
Source/cmLocalVisualStudio6Generator.cxx

@@ -1778,15 +1778,15 @@ void cmLocalVisualStudio6Generator
       std::set<std::string> minsizeDefinesSet;
       std::set<std::string> debugrelDefinesSet;
 
-      this->AddCompileDefinitions(definesSet, &target, "");
+      this->AddCompileDefinitions(definesSet, &target, "", linkLanguage);
       this->AddCompileDefinitions(debugDefinesSet, &target,
-                                  "DEBUG");
+                                  "DEBUG", linkLanguage);
       this->AddCompileDefinitions(releaseDefinesSet, &target,
-                                  "RELEASE");
+                                  "RELEASE", linkLanguage);
       this->AddCompileDefinitions(minsizeDefinesSet, &target,
-                                  "MINSIZEREL");
+                                  "MINSIZEREL", linkLanguage);
       this->AddCompileDefinitions(debugrelDefinesSet, &target,
-                                  "RELWITHDEBINFO");
+                                  "RELWITHDEBINFO", linkLanguage);
 
       std::string defines = " ";
       std::string debugDefines = " ";

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

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

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

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

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

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

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