Преглед изворни кода

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)
Andrew Paprocki пре 6 година
родитељ
комит
a080914274

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

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

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

@@ -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

+ 5 - 0
Help/release/dev/fortran-compiler-id.rst

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

+ 46 - 0
Source/cmGeneratorExpressionNode.cxx

@@ -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;

+ 3 - 0
Tests/CMakeLists.txt

@@ -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)

+ 17 - 0
Tests/CompileOptions/CMakeLists.txt

@@ -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()

+ 11 - 4
Tests/CompileOptions/main.cpp

@@ -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;
 }

+ 1 - 0
Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID-result.txt

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

+ 9 - 0
Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID-stderr.txt

@@ -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\)

+ 4 - 0
Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID.cmake

@@ -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")

+ 1 - 0
Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION-result.txt

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

+ 9 - 0
Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION-stderr.txt

@@ -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\)

+ 4 - 0
Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION.cmake

@@ -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")

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

@@ -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)