Commit e214abda authored by Robert Maynard's avatar Robert Maynard Committed by Brad King

Genex: Add COMPILE_LANG_AND_ID generator expression

parent f84ed796
......@@ -2199,6 +2199,7 @@ syn keyword cmakeGeneratorExpressions contained
\ COMPILE_DEFINITIONS
\ COMPILE_FEATURES
\ COMPILE_LANGUAGE
\ COMPILE_LANG_AND_ID
\ COMPILING_CUDA
\ COMPILING_CXX
\ CONFIG
......
......@@ -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,
......
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.
......@@ -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 }
};
......
......@@ -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>
)
......
......@@ -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}
......
......@@ -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
......
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\)
add_custom_target(drive)
add_custom_command(TARGET drive PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANG_AND_ID>
)
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\)
add_custom_target(drive
COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANG_AND_ID:LANG,ID>
)
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\)
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>
)
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\)
add_library(empty empty.$<COMPILE_LANG_AND_ID:C,MSVC>)
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\)
include(CTest)
enable_testing()
add_test(NAME dummy COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANG_AND_ID:CXX,GNU>)
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.
install(FILES
empty.$<COMPILE_LANG_AND_ID:C,MSVC>
DESTINATION src
)
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\)
add_library(empty)
target_sources(empty PRIVATE empty.$<COMPILE_LANG_AND_ID>)
enable_language(C)
add_executable(empty empty.c)
target_compile_options(empty PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,GNU>:$<TARGET_EXISTS:too,many,parameters>>)
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment