Fortran: Add compiler ID/Version generator expressions

Adds `Fortran_COMPILER_ID` and `Fortran_COMPILER_VERSION` generator
expression support to match equivalent `C_COMPILER_ID`,
`CXX_COMPILER_ID`, `C_COMPILER_VERSION`, and `CXX_COMPILER_VERSION`
support.

This is very helpful in the case where the C/C++ compiler suite is a
different type of compiler from the platform Fortran compiler and
projects use generator expressions to assign compiler flags and
definitions.  (e.g. `GNU` C/C++ and `SunPro` Fortran on Linux)
This commit is contained in:
Andrew Paprocki 2019-01-14 09:12:38 -05:00 committed by Brad King
parent a61c061b61
commit a080914274
14 changed files with 127 additions and 4 deletions

View File

@ -2212,6 +2212,8 @@ syn keyword cmakeGeneratorExpressions contained
\ DEBUG_MODE
\ EXPORT
\ FOO_EXTRA_THINGS
\ Fortran_COMPILER_ID
\ Fortran_COMPILER_VERSION
\ GENEX_EVAL
\ GNU
\ IF

View File

@ -122,12 +122,19 @@ Variable Queries
``1`` if the CMake-id of the CXX compiler matches ``compiler_id``,
otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<Fortran_COMPILER_ID:compiler_id>``
``1`` if the CMake-id of the Fortran compiler matches ``compiler_id``,
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``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<CXX_COMPILER_VERSION:version>``
``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<Fortran_COMPILER_VERSION:version>``
``1`` if the version of the Fortran compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<TARGET_POLICY:policy>``
``1`` if the ``policy`` was NEW when the 'head' target was created,
else ``0``. If the ``policy`` was not set, the warning message for the policy
@ -339,12 +346,18 @@ Variable Queries
``$<CXX_COMPILER_ID>``
The CMake-id of the CXX compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<Fortran_COMPILER_ID>``
The CMake-id of the Fortran compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<C_COMPILER_VERSION>``
The version of the C compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<CXX_COMPILER_VERSION>``
The version of the CXX compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<Fortran_COMPILER_VERSION>``
The version of the Fortran compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<COMPILE_LANGUAGE>``
The compile language of source files when evaluating compile options.
See :ref:`the related boolean expression

View File

@ -0,0 +1,5 @@
Fortran_COMPILER_ID
-------------------
* The ``$<Fortran_COMPILER_ID:...>`` and ``$<Fortran_COMPILER_VERSION:...>``
:manual:`generator expressions <cmake-generator-expressions(7)>` were added.

View File

@ -692,6 +692,28 @@ static const struct CXXCompilerIdNode : public CompilerIdNode
}
} cxxCompilerIdNode;
static const struct FortranCompilerIdNode : public CompilerIdNode
{
FortranCompilerIdNode() {}
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
{
if (!context->HeadTarget) {
reportError(
context, content->GetOriginalExpression(),
"$<Fortran_COMPILER_ID> may only be used with binary targets. It may "
"not be used with add_custom_command or add_custom_target.");
return std::string();
}
return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
"Fortran");
}
} fortranCompilerIdNode;
struct CompilerVersionNode : public cmGeneratorExpressionNode
{
CompilerVersionNode() {}
@ -773,6 +795,28 @@ static const struct CxxCompilerVersionNode : public CompilerVersionNode
}
} cxxCompilerVersionNode;
static const struct FortranCompilerVersionNode : public CompilerVersionNode
{
FortranCompilerVersionNode() {}
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
{
if (!context->HeadTarget) {
reportError(
context, content->GetOriginalExpression(),
"$<Fortran_COMPILER_VERSION> may only be used with binary targets. "
"It may not be used with add_custom_command or add_custom_target.");
return std::string();
}
return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
"Fortran");
}
} fortranCompilerVersionNode;
struct PlatformIdNode : public cmGeneratorExpressionNode
{
PlatformIdNode() {}
@ -2024,6 +2068,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
nodeMap["NOT"] = &notNode;
nodeMap["C_COMPILER_ID"] = &cCompilerIdNode;
nodeMap["CXX_COMPILER_ID"] = &cxxCompilerIdNode;
nodeMap["Fortran_COMPILER_ID"] = &fortranCompilerIdNode;
nodeMap["VERSION_GREATER"] = &versionGreaterNode;
nodeMap["VERSION_GREATER_EQUAL"] = &versionGreaterEqNode;
nodeMap["VERSION_LESS"] = &versionLessNode;
@ -2031,6 +2076,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
nodeMap["VERSION_EQUAL"] = &versionEqualNode;
nodeMap["C_COMPILER_VERSION"] = &cCompilerVersionNode;
nodeMap["CXX_COMPILER_VERSION"] = &cxxCompilerVersionNode;
nodeMap["Fortran_COMPILER_VERSION"] = &fortranCompilerVersionNode;
nodeMap["PLATFORM_ID"] = &platformIdNode;
nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode;
nodeMap["CONFIGURATION"] = &configurationNode;

View File

@ -436,6 +436,9 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(PolicyScope PolicyScope)
ADD_TEST_MACRO(EmptyLibrary EmptyLibrary)
ADD_TEST_MACRO(CompileDefinitions CompileDefinitions)
if(CMAKE_Fortran_COMPILER)
set(CompileOptions_BUILD_OPTIONS -DTEST_FORTRAN=1)
endif()
ADD_TEST_MACRO(CompileOptions CompileOptions)
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
ADD_TEST_MACRO(AliasTarget AliasTarget)

View File

@ -4,6 +4,10 @@ project(CompileOptions)
add_library(testlib other.cpp)
if(TEST_FORTRAN)
enable_language(Fortran)
endif()
add_executable(CompileOptions main.cpp)
macro(get_compiler_test_genex lst lang)
@ -13,6 +17,9 @@ endmacro()
get_compiler_test_genex(c_tests C)
get_compiler_test_genex(cxx_tests CXX)
if(TEST_FORTRAN)
get_compiler_test_genex(fortran_tests Fortran)
endif()
set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS
"-DTEST_DEFINE"
@ -21,6 +28,7 @@ set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS
"SHELL:" # produces no options
${c_tests}
${cxx_tests}
${fortran_tests}
)
if(BORLAND OR WATCOM)
# these compilers do not support separate -D flags
@ -54,3 +62,12 @@ target_compile_definitions(CompileOptions
"EXPECTED_C_COMPILER_VERSION=\"${CMAKE_C_COMPILER_VERSION}\""
"EXPECTED_CXX_COMPILER_VERSION=\"${CMAKE_CXX_COMPILER_VERSION}\""
)
if(TEST_FORTRAN)
# Definitions for the C++ code to test the values
target_compile_definitions(CompileOptions
PRIVATE
"TEST_FORTRAN"
"EXPECTED_Fortran_COMPILER_VERSION=\"${CMAKE_Fortran_COMPILER_VERSION}\""
)
endif()

View File

@ -47,10 +47,17 @@ int main()
#endif
&&
strcmp(EXPECTED_C_COMPILER_VERSION, TEST_C_COMPILER_VERSION) == 0 &&
strcmp(EXPECTED_CXX_COMPILER_VERSION, TEST_CXX_COMPILER_VERSION) ==
0 &&
TEST_C_COMPILER_VERSION_EQUALITY == 1 &&
TEST_CXX_COMPILER_VERSION_EQUALITY == 1)
strcmp(EXPECTED_CXX_COMPILER_VERSION, TEST_CXX_COMPILER_VERSION) == 0
#ifdef TEST_FORTRAN
&& strcmp(EXPECTED_Fortran_COMPILER_VERSION,
TEST_Fortran_COMPILER_VERSION) == 0
#endif
&& TEST_C_COMPILER_VERSION_EQUALITY == 1 &&
TEST_CXX_COMPILER_VERSION_EQUALITY == 1
#ifdef TEST_FORTRAN
&& TEST_Fortran_COMPILER_VERSION_EQUALITY == 1
#endif
)
? 0
: 1;
}

View File

@ -0,0 +1,9 @@
CMake Error at NonValidTarget-Fortran_COMPILER_ID.cmake:1 \(add_custom_command\):
Error evaluating generator expression:
\$<Fortran_COMPILER_ID>
\$<Fortran_COMPILER_ID> may only be used with binary targets. It may not be
used with add_custom_command or add_custom_target.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,4 @@
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c"
COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<Fortran_COMPILER_ID>.c"
)
add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")

View File

@ -0,0 +1,9 @@
CMake Error at NonValidTarget-Fortran_COMPILER_VERSION.cmake:1 \(add_custom_command\):
Error evaluating generator expression:
\$<Fortran_COMPILER_VERSION>
\$<Fortran_COMPILER_VERSION> may only be used with binary targets. It may
not be used with add_custom_command or add_custom_target.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,4 @@
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c"
COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<Fortran_COMPILER_VERSION>.c"
)
add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")

View File

@ -15,8 +15,10 @@ run_cmake(BadSHELL_PATH)
run_cmake(CMP0044-WARN)
run_cmake(NonValidTarget-C_COMPILER_ID)
run_cmake(NonValidTarget-CXX_COMPILER_ID)
run_cmake(NonValidTarget-Fortran_COMPILER_ID)
run_cmake(NonValidTarget-C_COMPILER_VERSION)
run_cmake(NonValidTarget-CXX_COMPILER_VERSION)
run_cmake(NonValidTarget-Fortran_COMPILER_VERSION)
run_cmake(NonValidTarget-TARGET_BUNDLE_DIR)
run_cmake(NonValidTarget-TARGET_BUNDLE_CONTENT_DIR)
run_cmake(NonValidTarget-TARGET_PROPERTY)