Commit 4b68baa7 authored by Brad King's avatar Brad King Committed by Kitware Robot

Merge topic 'compiler_id_gen_exp_supports_multiple_ids'

162555d7 Help: Add release notes for updated generator expressions
808b8180 Genex: CompileLang and CompileLangAndId now match against a list of ids
9fd602bf Genex: PlatformId now can match against a list of ids.
ec66af20 Genex: CompilerId now can match against a list of ids.
2d4787fc Genex: Add more extensive support for an unbounded number of parameters
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !3405
parents d4108f55 162555d7
......@@ -110,24 +110,30 @@ Variable Queries
The mapping in :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by
this expression when it is evaluated on a property on an :prop_tgt:`IMPORTED`
target.
``$<PLATFORM_ID:platform_id>``
``1`` if the CMake's platform id matches ``platform_id``
otherwise ``0``.
``$<PLATFORM_ID:platform_ids>``
where ``platform_ids`` is a comma-separated list.
``1`` if the CMake's platform id matches any one of the entries in
``platform_ids``, otherwise ``0``.
See also the :variable:`CMAKE_SYSTEM_NAME` variable.
``$<C_COMPILER_ID:compiler_id>``
``1`` if the CMake's compiler id of the C compiler matches ``compiler_id``,
otherwise ``0``.
``$<C_COMPILER_ID:compiler_ids>``
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the C compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<CXX_COMPILER_ID:compiler_id>``
``1`` if the CMake's compiler id of the CXX compiler matches ``compiler_id``,
otherwise ``0``.
``$<CUDA_COMPILER_ID:compiler_id>``
``1`` if the CMake's compiler id of the CUDA compiler matches ``compiler_id``,
otherwise ``0``.
``$<CXX_COMPILER_ID:compiler_ids>``
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the CXX compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<Fortran_COMPILER_ID:compiler_id>``
``1`` if the CMake's compiler id of the Fortran compiler matches ``compiler_id``,
otherwise ``0``.
``$<CUDA_COMPILER_ID:compiler_ids>``
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the CUDA compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<Fortran_COMPILER_ID:compiler_ids>``
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the Fortran compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<C_COMPILER_VERSION:version>``
``1`` if the version of the C compiler matches ``version``, otherwise ``0``.
......@@ -158,20 +164,20 @@ Variable Queries
.. _`Boolean COMPILE_LANGUAGE Generator Expression`:
``$<COMPILE_LANG_AND_ID:language,compiler_id>``
``$<COMPILE_LANG_AND_ID:language,compiler_ids>``
``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
the CMake's compiler id of the language compiler matches any one of the
entries in ``compiler_ids``, otherwise ``0``. This expression is a short form
for the combination of ``$<COMPILE_LANGUAGE:language>`` and
``$<LANG_COMPILER_ID:compiler_ids>``. 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>
PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,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>
)
......@@ -194,10 +200,10 @@ Variable Queries
$<$<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,
compile definitions, and include directories for source files of a
``$<COMPILE_LANGUAGE:languages>``
``1`` when the language used for compilation unit matches any of the entries
in ``languages``, otherwise ``0``. This expression may be used to specify
compile options, compile definitions, and include directories for source files of a
particular language in a target. For example:
.. code-block:: cmake
......@@ -211,7 +217,7 @@ Variable Queries
$<$<COMPILE_LANGUAGE:CUDA>:COMPILING_CUDA>
)
target_include_directories(myapp
PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/opt/foo/cxx_headers>
PRIVATE $<$<COMPILE_LANGUAGE:CXX,CUDA>:/opt/foo/headers>
)
This specifies the use of the ``-fno-exceptions`` compile option,
......
genex-comma-separated
---------------------
* The :manual:`generator expressions <cmake-generator-expressions(7)>`
``C_COMPILER_ID``, ``CXX_COMPILER_ID``, ``CUDA_COMPILER_ID``,
``Fortran_COMPILER_ID``, ``COMPILE_LANGUAGE``, ``COMPILE_LANG_AND_ID``, and
``PLATFORM_ID`` learned to support matching one value from a comma-separated
list.
......@@ -166,9 +166,13 @@ std::string GeneratorExpressionContent::EvaluateParameters(
reportError(context, this->GetOriginalExpression(),
"$<" + identifier +
"> expression requires at least one parameter.");
}
if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
parameters.size() > 1) {
} else if (numExpected == cmGeneratorExpressionNode::TwoOrMoreParameters &&
parameters.size() < 2) {
reportError(context, this->GetOriginalExpression(),
"$<" + identifier +
"> expression requires at least two parameters.");
} else if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
parameters.size() > 1) {
reportError(context, this->GetOriginalExpression(),
"$<" + identifier +
"> expression requires one or zero parameters.");
......
......@@ -632,7 +632,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
{
}
int NumExpectedParameters() const override { return OneOrZeroParameters; }
int NumExpectedParameters() const override { return ZeroOrMoreParameters; }
std::string Evaluate(
const std::vector<std::string>& parameters,
......@@ -664,36 +664,39 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
if (parameters.empty()) {
return compilerId;
}
static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
if (!compilerIdValidator.find(parameters.front())) {
reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
return std::string();
}
if (compilerId.empty()) {
return parameters.front().empty() ? "1" : "0";
}
static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
if (strcmp(parameters.front().c_str(), compilerId.c_str()) == 0) {
return "1";
}
for (auto& param : parameters) {
if (cmsysString_strcasecmp(parameters.front().c_str(),
compilerId.c_str()) == 0) {
switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) {
case cmPolicies::WARN: {
std::ostringstream e;
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044);
context->LG->GetCMakeInstance()->IssueMessage(
MessageType::AUTHOR_WARNING, e.str(), context->Backtrace);
CM_FALLTHROUGH;
if (!compilerIdValidator.find(param)) {
reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
return std::string();
}
if (strcmp(param.c_str(), compilerId.c_str()) == 0) {
return "1";
}
if (cmsysString_strcasecmp(param.c_str(), compilerId.c_str()) == 0) {
switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) {
case cmPolicies::WARN: {
std::ostringstream e;
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044);
context->LG->GetCMakeInstance()->IssueMessage(
MessageType::AUTHOR_WARNING, e.str(), context->Backtrace);
CM_FALLTHROUGH;
}
case cmPolicies::OLD:
return "1";
case cmPolicies::NEW:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
break;
}
case cmPolicies::OLD:
return "1";
case cmPolicies::NEW:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
break;
}
}
return "0";
......@@ -773,7 +776,7 @@ struct PlatformIdNode : public cmGeneratorExpressionNode
{
PlatformIdNode() {} // NOLINT(modernize-use-equals-default)
int NumExpectedParameters() const override { return OneOrZeroParameters; }
int NumExpectedParameters() const override { return ZeroOrMoreParameters; }
std::string Evaluate(
const std::vector<std::string>& parameters,
......@@ -791,8 +794,10 @@ struct PlatformIdNode : public cmGeneratorExpressionNode
return parameters.front().empty() ? "1" : "0";
}
if (parameters.front() == platformId) {
return "1";
for (auto& param : parameters) {
if (param == platformId) {
return "1";
}
}
return "0";
}
......@@ -946,7 +951,7 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
{
CompileLanguageNode() {} // NOLINT(modernize-use-equals-default)
int NumExpectedParameters() const override { return OneOrZeroParameters; }
int NumExpectedParameters() const override { return ZeroOrMoreParameters; }
std::string Evaluate(
const std::vector<std::string>& parameters,
......@@ -977,7 +982,13 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
if (parameters.empty()) {
return context->Language;
}
return context->Language == parameters.front() ? "1" : "0";
for (auto& param : parameters) {
if (context->Language == param) {
return "1";
}
}
return "0";
}
} languageNode;
......@@ -985,7 +996,7 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
{
CompileLanguageAndIdNode() {} // NOLINT(modernize-use-equals-default)
int NumExpectedParameters() const override { return 2; }
int NumExpectedParameters() const override { return TwoOrMoreParameters; }
std::string Evaluate(
const std::vector<std::string>& parameters,
......@@ -1018,7 +1029,8 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
const std::string& lang = context->Language;
if (lang == parameters.front()) {
std::vector<std::string> idParameter = { parameters[1] };
std::vector<std::string> idParameter((parameters.cbegin() + 1),
parameters.cend());
return CompilerIdNode{ lang.c_str() }.EvaluateWithLanguage(
idParameter, context, content, dagChecker, lang);
}
......
......@@ -20,7 +20,9 @@ struct cmGeneratorExpressionNode
{
DynamicParameters = 0,
OneOrMoreParameters = -1,
OneOrZeroParameters = -2
TwoOrMoreParameters = -2,
ZeroOrMoreParameters = -3,
OneOrZeroParameters = -4
};
virtual ~cmGeneratorExpressionNode() = default;
......
......@@ -34,6 +34,7 @@ target_compile_definitions(consumer
CONSUMER_LANG_$<COMPILE_LANGUAGE>
LANG_IS_CXX=$<COMPILE_LANGUAGE:CXX>
LANG_IS_C=$<COMPILE_LANGUAGE:C>
LANG_IS_C_OR_CXX=$<COMPILE_LANGUAGE:C,CXX>
)
if(CMAKE_GENERATOR MATCHES "Visual Studio|Xcode")
target_compile_definitions(consumer
......
......@@ -35,6 +35,10 @@
# endif
#endif
#if !LANG_IS_C_OR_CXX
# error Expected LANG_IS_C_OR_CXX
#endif
void consumer_c()
{
}
......@@ -7,9 +7,11 @@ add_executable(target_compile_options
"${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
)
target_compile_options(target_compile_options
PRIVATE $<$<CXX_COMPILER_ID:GNU>:-DMY_PRIVATE_DEFINE>
PRIVATE $<$<CXX_COMPILER_ID:AppleClang,Clang,GNU>:-DMY_PRIVATE_DEFINE>
PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-DMY_PUBLIC_DEFINE>
PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>:-DMY_MUTLI_COMP_PUBLIC_DEFINE>
INTERFACE $<$<CXX_COMPILER_ID:GNU>:-DMY_INTERFACE_DEFINE>
INTERFACE $<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-DMY_MULTI_COMP_INTERFACE_DEFINE>
)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
......@@ -17,6 +19,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
PRIVATE
"DO_GNU_TESTS"
)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_definitions(target_compile_options
PRIVATE
"DO_CLANG_TESTS"
)
endif()
add_executable(consumer
......@@ -40,7 +47,7 @@ if(CMAKE_GENERATOR MATCHES "Visual Studio")
endif()
target_compile_options(consumer
PRIVATE $<$<CXX_COMPILER_ID:GNU>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>>
PRIVATE $<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>>
)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
......@@ -48,6 +55,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
PRIVATE
"DO_GNU_TESTS"
)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_definitions(consumer
PRIVATE
"DO_CLANG_TESTS"
)
endif()
# Test no items
......
......@@ -13,6 +13,30 @@
# error Expected MY_INTERFACE_DEFINE
# endif
# ifndef MY_MULTI_COMP_INTERFACE_DEFINE
# error Expected MY_MULTI_COMP_INTERFACE_DEFINE
# endif
# ifndef MY_MUTLI_COMP_PUBLIC_DEFINE
# error Expected MY_MUTLI_COMP_PUBLIC_DEFINE
# endif
#endif
#ifdef DO_CLANG_TESTS
# ifdef MY_PRIVATE_DEFINE
# error Unexpected MY_PRIVATE_DEFINE
# endif
# ifndef MY_MULTI_COMP_INTERFACE_DEFINE
# error Expected MY_MULTI_COMP_INTERFACE_DEFINE
# endif
# ifndef MY_MUTLI_COMP_PUBLIC_DEFINE
# error Expected MY_MUTLI_COMP_PUBLIC_DEFINE
# endif
#endif
#ifndef CONSUMER_LANG_CXX
......
......@@ -9,12 +9,32 @@
# error Expected MY_PUBLIC_DEFINE
# endif
# ifndef MY_MUTLI_COMP_PUBLIC_DEFINE
# error Expected MY_MUTLI_COMP_PUBLIC_DEFINE
# endif
# ifdef MY_INTERFACE_DEFINE
# error Unexpected MY_INTERFACE_DEFINE
# endif
#endif
#ifdef DO_CLANG_TESTS
# ifndef MY_PRIVATE_DEFINE
# error Expected MY_PRIVATE_DEFINE
# endif
# ifdef MY_PUBLIC_DEFINE
# error Unexpected MY_PUBLIC_DEFINE
# endif
# ifndef MY_MUTLI_COMP_PUBLIC_DEFINE
# error Expected MY_MUTLI_COMP_PUBLIC_DEFINE
# endif
#endif
int main()
{
return 0;
......
......@@ -220,6 +220,7 @@ add_custom_target(check-part3 ALL
-Dtest_early_termination_2=$<$<1:>:,
-Dsystem_name=${CMAKE_HOST_SYSTEM_NAME}
-Dtest_platform_id=$<PLATFORM_ID>
-Dtest_platform_id_supported=$<PLATFORM_ID:Linux,Windows,Darwin>
-Dtest_platform_id_Linux=$<PLATFORM_ID:Linux>
-Dtest_platform_id_Windows=$<PLATFORM_ID:Windows>
-Dtest_platform_id_Darwin=$<PLATFORM_ID:Darwin>
......
......@@ -28,11 +28,16 @@ check(test_early_termination_2 "$<:,")
check(test_platform_id "${system_name}")
foreach(system Linux Windows Darwin)
if(system_name STREQUAL system)
check(test_platform_id_supported 1)
check(test_platform_id_${system} 1)
set(platform_supported 1)
else()
check(test_platform_id_${system} 0)
endif()
endforeach()
if(NOT platform_supported)
check(test_platform_id_supported 0)
endif()
check(lower_case "mi,xed")
check(upper_case "MIX,ED")
check(make_c_identifier "_4f_oo__bar__")
......
......@@ -3,7 +3,6 @@ CMake Error at COMPILE_LANG_AND_ID-add_custom_command.cmake:2 \(add_custom_comma
\$<COMPILE_LANG_AND_ID>
\$<COMPILE_LANG_AND_ID> expression requires 2 comma separated parameters,
but got 0 instead.
\$<COMPILE_LANG_AND_ID> expression requires at least two parameters.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
......@@ -3,7 +3,6 @@ CMake Error at COMPILE_LANG_AND_ID-target_sources.cmake:2 \(target_sources\):
\$<COMPILE_LANG_AND_ID>
\$<COMPILE_LANG_AND_ID> expression requires 2 comma separated parameters,
but got 0 instead.
\$<COMPILE_LANG_AND_ID> expression requires at least two parameters.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
......@@ -2,4 +2,4 @@
add_library(foo STATIC foo.cpp)
string(TOLOWER ${CMAKE_CXX_COMPILER_ID} compiler_id)
target_compile_definitions(foo PRIVATE Foo=$<CXX_COMPILER_ID:${compiler_id}>)
target_compile_definitions(foo PRIVATE Foo=$<CXX_COMPILER_ID:invalid,${compiler_id}>)
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