浏览代码

Genex: Add COMPILE_LANG_AND_ID generator expression

Robert Maynard 6 年之前
父节点
当前提交
e214abdaab
共有 30 个文件被更改,包括 212 次插入1 次删除
  1. 1 0
      Auxiliary/vim/syntax/cmake.vim
  2. 36 0
      Help/manual/cmake-generator-expressions.7.rst
  3. 7 0
      Help/release/dev/genex-COMPILE_LANG_AND_ID.rst
  4. 46 0
      Source/cmGeneratorExpressionNode.cxx
  5. 1 1
      Tests/CMakeCommands/target_compile_options/CMakeLists.txt
  6. 1 0
      Tests/CompileOptions/CMakeLists.txt
  7. 3 0
      Tests/CompileOptions/main.cpp
  8. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command-result.txt
  9. 9 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt
  10. 4 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command.cmake
  11. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target-result.txt
  12. 11 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt
  13. 4 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target.cmake
  14. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable-result.txt
  15. 11 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable-stderr.txt
  16. 5 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable.cmake
  17. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library-result.txt
  18. 11 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library-stderr.txt
  19. 2 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library.cmake
  20. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test-result.txt
  21. 11 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test-stderr.txt
  22. 5 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test.cmake
  23. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install-result.txt
  24. 9 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install-stderr.txt
  25. 5 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install.cmake
  26. 1 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources-result.txt
  27. 9 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources-stderr.txt
  28. 2 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources.cmake
  29. 4 0
      Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-unknown-lang.cmake
  30. 8 0
      Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake

+ 1 - 0
Auxiliary/vim/syntax/cmake.vim

@@ -2199,6 +2199,7 @@ syn keyword cmakeGeneratorExpressions contained
             \ COMPILE_DEFINITIONS
             \ COMPILE_DEFINITIONS
             \ COMPILE_FEATURES
             \ COMPILE_FEATURES
             \ COMPILE_LANGUAGE
             \ COMPILE_LANGUAGE
+            \ COMPILE_LANG_AND_ID
             \ COMPILING_CUDA
             \ COMPILING_CUDA
             \ COMPILING_CXX
             \ COMPILING_CXX
             \ CONFIG
             \ CONFIG

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

@@ -158,6 +158,42 @@ Variable Queries
 
 
 .. _`Boolean COMPILE_LANGUAGE Generator Expression`:
 .. _`Boolean COMPILE_LANGUAGE Generator Expression`:
 
 
+``$<COMPILE_LANG_AND_ID:language,compiler_id>``
+  ``1`` when the language used for compilation unit matches ``language`` and
+  the CMake's compiler id of the language compiler matches ``compiler_id``,
+  otherwise ``0``. This expression is a short form for the combination of
+  ``$<COMPILE_LANGUAGE:language>`` and ``$<LANG_COMPILER_ID:compiler_id>``.
+  This expression may be used to specify compile options,
+  compile definitions, and include directories for source files of a
+  particular language and compiler combination in a target. For example:
+
+  .. code-block:: cmake
+
+    add_executable(myapp main.cpp foo.c bar.cpp zot.cu)
+    target_compile_definitions(myapp
+      PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,Clang>:COMPILING_CXX_WITH_CLANG>
+              $<$<COMPILE_LANG_AND_ID:CXX,Intel>:COMPILING_CXX_WITH_INTEL>
+              $<$<COMPILE_LANG_AND_ID:C,Clang>:COMPILING_C_WITH_CLANG>
+    )
+
+  This specifies the use of different compile definitions based on both
+  the compiler id and compilation language. This example will have a
+  ``COMPILING_CXX_WITH_CLANG`` compile definition when Clang is the CXX
+  compiler, and ``COMPILING_CXX_WITH_INTEL`` when Intel is the CXX compiler.
+  Likewise when the C compiler is Clang it will only see the  ``COMPILING_C_WITH_CLANG``
+  definition.
+
+  Without the ``COMPILE_LANG_AND_ID`` generator expression the same logic
+  would be expressed as:
+
+  .. code-block:: cmake
+
+    target_compile_definitions(myapp
+      PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:Clang>>:COMPILING_CXX_WITH_CLANG>
+              $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:Intel>>:COMPILING_CXX_WITH_INTEL>
+              $<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:Clang>>:COMPILING_C_WITH_CLANG>
+    )
+
 ``$<COMPILE_LANGUAGE:language>``
 ``$<COMPILE_LANGUAGE:language>``
   ``1`` when the language used for compilation unit matches ``language``,
   ``1`` when the language used for compilation unit matches ``language``,
   otherwise ``0``.  This expression may be used to specify compile options,
   otherwise ``0``.  This expression may be used to specify compile options,

+ 7 - 0
Help/release/dev/genex-COMPILE_LANG_AND_ID.rst

@@ -0,0 +1,7 @@
+genex-COMPILE_LANG_AND_ID
+--------------------------
+
+* A new ``COMPILE_LANG_AND_ID`` generator expression was introduced to
+  allow specification of compile options for target files based on the
+  :variable:`CMAKE_<LANG>_COMPILER_ID`  and :prop_sf:`LANGUAGE` and of
+  each source file.

+ 46 - 0
Source/cmGeneratorExpressionNode.cxx

@@ -981,6 +981,51 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
   }
   }
 } languageNode;
 } languageNode;
 
 
+static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
+{
+  CompileLanguageAndIdNode() {} // NOLINT(modernize-use-equals-default)
+
+  int NumExpectedParameters() const override { return 2; }
+
+  std::string Evaluate(
+    const std::vector<std::string>& parameters,
+    cmGeneratorExpressionContext* context,
+    const GeneratorExpressionContent* content,
+    cmGeneratorExpressionDAGChecker* dagChecker) const override
+  {
+    if (!context->HeadTarget || context->Language.empty()) {
+      // reportError(context, content->GetOriginalExpression(), "");
+      reportError(
+        context, content->GetOriginalExpression(),
+        "$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary targets "
+        "to specify include directories, compile definitions, and compile "
+        "options.  It may not be used with the add_custom_command, "
+        "add_custom_target, or file(GENERATE) commands.");
+      return std::string();
+    }
+    cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
+    std::string genName = gg->GetName();
+    if (genName.find("Makefiles") == std::string::npos &&
+        genName.find("Ninja") == std::string::npos &&
+        genName.find("Visual Studio") == std::string::npos &&
+        genName.find("Xcode") == std::string::npos &&
+        genName.find("Watcom WMake") == std::string::npos) {
+      reportError(
+        context, content->GetOriginalExpression(),
+        "$<COMPILE_LANG_AND_ID:lang,id> not supported for this generator.");
+      return std::string();
+    }
+
+    const std::string& lang = context->Language;
+    if (lang == parameters.front()) {
+      std::vector<std::string> idParameter = { parameters[1] };
+      return CompilerIdNode{ lang.c_str() }.EvaluateWithLanguage(
+        idParameter, context, content, dagChecker, lang);
+    }
+    return "0";
+  }
+} languageAndIdNode;
+
 #define TRANSITIVE_PROPERTY_NAME(PROPERTY) , "INTERFACE_" #PROPERTY
 #define TRANSITIVE_PROPERTY_NAME(PROPERTY) , "INTERFACE_" #PROPERTY
 
 
 static const char* targetPropertyTransitiveWhitelist[] = {
 static const char* targetPropertyTransitiveWhitelist[] = {
@@ -2285,6 +2330,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
     { "INSTALL_PREFIX", &installPrefixNode },
     { "INSTALL_PREFIX", &installPrefixNode },
     { "JOIN", &joinNode },
     { "JOIN", &joinNode },
     { "LINK_ONLY", &linkOnlyNode },
     { "LINK_ONLY", &linkOnlyNode },
+    { "COMPILE_LANG_AND_ID", &languageAndIdNode },
     { "COMPILE_LANGUAGE", &languageNode },
     { "COMPILE_LANGUAGE", &languageNode },
     { "SHELL_PATH", &shellPathNode }
     { "SHELL_PATH", &shellPathNode }
   };
   };

+ 1 - 1
Tests/CMakeCommands/target_compile_options/CMakeLists.txt

@@ -8,7 +8,7 @@ add_executable(target_compile_options
 )
 )
 target_compile_options(target_compile_options
 target_compile_options(target_compile_options
   PRIVATE $<$<CXX_COMPILER_ID:GNU>:-DMY_PRIVATE_DEFINE>
   PRIVATE $<$<CXX_COMPILER_ID:GNU>:-DMY_PRIVATE_DEFINE>
-  PUBLIC $<$<CXX_COMPILER_ID:GNU>:-DMY_PUBLIC_DEFINE>
+  PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-DMY_PUBLIC_DEFINE>
   INTERFACE $<$<CXX_COMPILER_ID:GNU>:-DMY_INTERFACE_DEFINE>
   INTERFACE $<$<CXX_COMPILER_ID:GNU>:-DMY_INTERFACE_DEFINE>
 )
 )
 
 

+ 1 - 0
Tests/CompileOptions/CMakeLists.txt

@@ -25,6 +25,7 @@ set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS
   "-DTEST_DEFINE"
   "-DTEST_DEFINE"
   "-DNEEDS_ESCAPE=\"E$CAPE\""
   "-DNEEDS_ESCAPE=\"E$CAPE\""
   "$<$<CXX_COMPILER_ID:GNU>:-DTEST_DEFINE_GNU>"
   "$<$<CXX_COMPILER_ID:GNU>:-DTEST_DEFINE_GNU>"
+  "$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-DTEST_DEFINE_CXX_AND_GNU>"
   "SHELL:" # produces no options
   "SHELL:" # produces no options
   ${c_tests}
   ${c_tests}
   ${cxx_tests}
   ${cxx_tests}

+ 3 - 0
Tests/CompileOptions/main.cpp

@@ -10,6 +10,9 @@
 #  ifndef TEST_DEFINE_GNU
 #  ifndef TEST_DEFINE_GNU
 #    error Expected definition TEST_DEFINE_GNU
 #    error Expected definition TEST_DEFINE_GNU
 #  endif
 #  endif
+#  ifndef TEST_DEFINE_CXX_AND_GNU
+#    error Expected definition TEST_DEFINE_CXX_AND_GNU
+#  endif
 #endif
 #endif
 
 
 #ifndef NO_DEF_TESTS
 #ifndef NO_DEF_TESTS

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

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

+ 9 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt

@@ -0,0 +1,9 @@
+CMake Error at COMPILE_LANG_AND_ID-add_custom_command.cmake:2 \(add_custom_command\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANG_AND_ID>
+
+  \$<COMPILE_LANG_AND_ID> expression requires 2 comma separated parameters,
+  but got 0 instead.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 4 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command.cmake

@@ -0,0 +1,4 @@
+add_custom_target(drive)
+add_custom_command(TARGET drive PRE_BUILD
+  COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANG_AND_ID>
+)

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

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

+ 11 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt

@@ -0,0 +1,11 @@
+CMake Error at COMPILE_LANG_AND_ID-add_custom_target.cmake:2 \(add_custom_target\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANG_AND_ID:LANG,ID>
+
+  \$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary targets to
+  specify include directories, compile definitions, and compile options.  It
+  may not be used with the add_custom_command, add_custom_target, or
+  file\(GENERATE\) commands.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 4 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target.cmake

@@ -0,0 +1,4 @@
+
+add_custom_target(drive
+  COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANG_AND_ID:LANG,ID>
+)

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

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

+ 11 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable-stderr.txt

@@ -0,0 +1,11 @@
+CMake Error at COMPILE_LANG_AND_ID-add_executable.cmake:1 \(add_executable\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANG_AND_ID:C,MSVC>
+
+  \$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary targets to
+  specify include directories, compile definitions, and compile options.  It
+  may not be used with the add_custom_command, add_custom_target, or
+  file\(GENERATE\) commands.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 5 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable.cmake

@@ -0,0 +1,5 @@
+add_executable(empty main.c
+        $<$<COMPILE_LANG_AND_ID:C,MSVC>:empty.c>
+        $<$<COMPILE_LANG_AND_ID:C,GNU>:empty2.c>
+        $<$<COMPILE_LANG_AND_ID:C,Clang>:empty3.c>
+        )

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

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

+ 11 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library-stderr.txt

@@ -0,0 +1,11 @@
+CMake Error at COMPILE_LANG_AND_ID-add_library.cmake:2 \(add_library\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANG_AND_ID:C,MSVC>
+
+  \$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary targets to
+  specify include directories, compile definitions, and compile options.  It
+  may not be used with the add_custom_command, add_custom_target, or
+  file\(GENERATE\) commands.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 2 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library.cmake

@@ -0,0 +1,2 @@
+
+add_library(empty empty.$<COMPILE_LANG_AND_ID:C,MSVC>)

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

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

+ 11 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test-stderr.txt

@@ -0,0 +1,11 @@
+CMake Error at COMPILE_LANG_AND_ID-add_test.cmake:5 \(add_test\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANG_AND_ID:CXX,GNU>
+
+  \$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary targets to
+  specify include directories, compile definitions, and compile options.  It
+  may not be used with the add_custom_command, add_custom_target, or
+  file\(GENERATE\) commands.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

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

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

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

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

+ 9 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install-stderr.txt

@@ -0,0 +1,9 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANG_AND_ID:C,MSVC>
+
+  \$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary targets to
+  specify include directories, compile definitions, and compile options.  It
+  may not be used with the add_custom_command, add_custom_target, or
+  file\(GENERATE\) commands.

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

@@ -0,0 +1,5 @@
+
+install(FILES
+  empty.$<COMPILE_LANG_AND_ID:C,MSVC>
+  DESTINATION src
+)

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

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

+ 9 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources-stderr.txt

@@ -0,0 +1,9 @@
+CMake Error at COMPILE_LANG_AND_ID-target_sources.cmake:2 \(target_sources\):
+  Error evaluating generator expression:
+
+    \$<COMPILE_LANG_AND_ID>
+
+  \$<COMPILE_LANG_AND_ID> expression requires 2 comma separated parameters,
+  but got 0 instead.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 2 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources.cmake

@@ -0,0 +1,2 @@
+add_library(empty)
+target_sources(empty PRIVATE empty.$<COMPILE_LANG_AND_ID>)

+ 4 - 0
Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-unknown-lang.cmake

@@ -0,0 +1,4 @@
+
+enable_language(C)
+add_executable(empty empty.c)
+target_compile_options(empty PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,GNU>:$<TARGET_EXISTS:too,many,parameters>>)

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

@@ -31,6 +31,14 @@ run_cmake(COMPILE_LANGUAGE-add_executable)
 run_cmake(COMPILE_LANGUAGE-add_library)
 run_cmake(COMPILE_LANGUAGE-add_library)
 run_cmake(COMPILE_LANGUAGE-add_test)
 run_cmake(COMPILE_LANGUAGE-add_test)
 run_cmake(COMPILE_LANGUAGE-unknown-lang)
 run_cmake(COMPILE_LANGUAGE-unknown-lang)
+run_cmake(COMPILE_LANG_AND_ID-add_custom_target)
+run_cmake(COMPILE_LANG_AND_ID-add_custom_command)
+run_cmake(COMPILE_LANG_AND_ID-install)
+run_cmake(COMPILE_LANG_AND_ID-target_sources)
+run_cmake(COMPILE_LANG_AND_ID-add_executable)
+run_cmake(COMPILE_LANG_AND_ID-add_library)
+run_cmake(COMPILE_LANG_AND_ID-add_test)
+run_cmake(COMPILE_LANG_AND_ID-unknown-lang)
 run_cmake(TARGET_FILE-recursion)
 run_cmake(TARGET_FILE-recursion)
 run_cmake(OUTPUT_NAME-recursion)
 run_cmake(OUTPUT_NAME-recursion)
 run_cmake(TARGET_FILE_PREFIX)
 run_cmake(TARGET_FILE_PREFIX)