Browse Source

Genex: Allow COMPILE_LANGUAGE when processing include directories.

Issue an error if this is encountered by an IDE generator.
Stephen Kelly 10 năm trước cách đây
mục cha
commit
b734fa4471

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

+ 2 - 1
Source/cmGeneratorExpressionEvaluator.cxx

@@ -851,7 +851,8 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
       }
     else if (genName.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 "

+ 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/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.

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

+ 0 - 34
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;

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

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

+ 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

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

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