diff options
30 files changed, 212 insertions, 1 deletions
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 7fcdc72..fa4f60a 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -2199,6 +2199,7 @@ syn keyword cmakeGeneratorExpressions contained \ COMPILE_DEFINITIONS \ COMPILE_FEATURES \ COMPILE_LANGUAGE + \ COMPILE_LANG_AND_ID \ COMPILING_CUDA \ COMPILING_CXX \ CONFIG diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index df06284..f2e6597 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -158,6 +158,42 @@ Variable Queries .. _`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>`` ``1`` when the language used for compilation unit matches ``language``, otherwise ``0``. This expression may be used to specify compile options, diff --git a/Help/release/dev/genex-COMPILE_LANG_AND_ID.rst b/Help/release/dev/genex-COMPILE_LANG_AND_ID.rst new file mode 100644 index 0000000..27e0ebd --- /dev/null +++ b/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. diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 8c6fb34..709355a 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -981,6 +981,51 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode } } 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 static const char* targetPropertyTransitiveWhitelist[] = { @@ -2285,6 +2330,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "INSTALL_PREFIX", &installPrefixNode }, { "JOIN", &joinNode }, { "LINK_ONLY", &linkOnlyNode }, + { "COMPILE_LANG_AND_ID", &languageAndIdNode }, { "COMPILE_LANGUAGE", &languageNode }, { "SHELL_PATH", &shellPathNode } }; diff --git a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt index 1dedbae..a24cd53 100644 --- a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt +++ b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt @@ -8,7 +8,7 @@ add_executable(target_compile_options ) target_compile_options(target_compile_options 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> ) diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt index 15a993c..18896bf 100644 --- a/Tests/CompileOptions/CMakeLists.txt +++ b/Tests/CompileOptions/CMakeLists.txt @@ -25,6 +25,7 @@ set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS "-DTEST_DEFINE" "-DNEEDS_ESCAPE=\"E$CAPE\"" "$<$<CXX_COMPILER_ID:GNU>:-DTEST_DEFINE_GNU>" + "$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-DTEST_DEFINE_CXX_AND_GNU>" "SHELL:" # produces no options ${c_tests} ${cxx_tests} diff --git a/Tests/CompileOptions/main.cpp b/Tests/CompileOptions/main.cpp index d94a169..ebc1017 100644 --- a/Tests/CompileOptions/main.cpp +++ b/Tests/CompileOptions/main.cpp @@ -10,6 +10,9 @@ # ifndef TEST_DEFINE_GNU # error Expected definition TEST_DEFINE_GNU # endif +# ifndef TEST_DEFINE_CXX_AND_GNU +# error Expected definition TEST_DEFINE_CXX_AND_GNU +# endif #endif #ifndef NO_DEF_TESTS diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command-result.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt new file mode 100644 index 0000000..fc3c3de --- /dev/null +++ b/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\) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_command.cmake new file mode 100644 index 0000000..9bd5e8e --- /dev/null +++ b/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> +) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target-result.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt new file mode 100644 index 0000000..589e64b --- /dev/null +++ b/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\) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_custom_target.cmake new file mode 100644 index 0000000..398db19 --- /dev/null +++ b/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> +) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable-result.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable-stderr.txt new file mode 100644 index 0000000..3b3f38d --- /dev/null +++ b/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\) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_executable.cmake new file mode 100644 index 0000000..2245f50 --- /dev/null +++ b/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> + ) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library-result.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library-stderr.txt new file mode 100644 index 0000000..4cbf000 --- /dev/null +++ b/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\) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library.cmake new file mode 100644 index 0000000..044962a --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_library.cmake @@ -0,0 +1,2 @@ + +add_library(empty empty.$<COMPILE_LANG_AND_ID:C,MSVC>) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test-result.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test-stderr.txt new file mode 100644 index 0000000..26a5940 --- /dev/null +++ b/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\) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-add_test.cmake new file mode 100644 index 0000000..b5b6c2b --- /dev/null +++ b/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>) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install-result.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install-stderr.txt new file mode 100644 index 0000000..0c4ecd0 --- /dev/null +++ b/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. diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install.cmake new file mode 100644 index 0000000..c13eda6 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-install.cmake @@ -0,0 +1,5 @@ + +install(FILES + empty.$<COMPILE_LANG_AND_ID:C,MSVC> + DESTINATION src +) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources-result.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources-stderr.txt new file mode 100644 index 0000000..44d8684 --- /dev/null +++ b/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\) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-target_sources.cmake new file mode 100644 index 0000000..a2c9b03 --- /dev/null +++ b/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>) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-unknown-lang.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANG_AND_ID-unknown-lang.cmake new file mode 100644 index 0000000..b9e840b --- /dev/null +++ b/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>>) diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake index a491e99..8abf70d 100644 --- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake +++ b/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_test) 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(OUTPUT_NAME-recursion) run_cmake(TARGET_FILE_PREFIX) |