From 1efa246b4b53b6e372bf60e8e0b4eb58d4247e97 Mon Sep 17 00:00:00 2001
Message-Id: <1efa246b4b53b6e372bf60e8e0b4eb58d4247e97.1422998492.git.brad.king@kitware.com>
From: Brad King <brad.king@kitware.com>
Date: Tue, 3 Feb 2015 16:18:13 -0500
Subject: [PATCH] Fortran: Detect compiler version (#15372)

---
 Help/release/dev/compiler-version-Fortran.rst |  6 ++++
 Modules/CMakeDetermineCompilerId.cmake        | 30 +++++++++++++++++++-
 Modules/CMakeDetermineFortranCompiler.cmake   | 41 +++++++++++++++++++++++++++
 Modules/CMakeFortranCompilerId.F.in           | 19 +++++++++++++
 4 files changed, 95 insertions(+), 1 deletion(-)
 create mode 100644 Help/release/dev/compiler-version-Fortran.rst

diff --git a/Help/release/dev/compiler-version-Fortran.rst b/Help/release/dev/compiler-version-Fortran.rst
new file mode 100644
index 0000000..e10b206
--- /dev/null
+++ b/Help/release/dev/compiler-version-Fortran.rst
@@ -0,0 +1,6 @@
+compiler-version-Fortran
+------------------------
+
+* The version of some Fortran compilers is now detected and stored in the
+  :variable:`CMAKE_Fortran_COMPILER_VERSION <CMAKE_<LANG>_COMPILER_VERSION>`
+  variable.
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index dfed00e..bc90260 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -409,12 +409,22 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
     # Read the compiler identification string from the executable file.
     set(COMPILER_ID)
     set(COMPILER_VERSION)
+    set(COMPILER_VERSION_MAJOR 0)
+    set(COMPILER_VERSION_MINOR 0)
+    set(COMPILER_VERSION_PATCH 0)
+    set(HAVE_COMPILER_VERSION_MAJOR 0)
+    set(HAVE_COMPILER_VERSION_MINOR 0)
+    set(HAVE_COMPILER_VERSION_PATCH 0)
+    set(DIGIT_VALUE_1 1)
+    set(DIGIT_VALUE_2 10)
+    set(DIGIT_VALUE_3 100)
+    set(DIGIT_VALUE_4 1000)
     set(PLATFORM_ID)
     set(ARCHITECTURE_ID)
     set(SIMULATE_ID)
     set(SIMULATE_VERSION)
     file(STRINGS ${file}
-      CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 6 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
+      CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 18 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
     set(COMPILER_ID_TWICE)
     foreach(info ${CMAKE_${lang}_COMPILER_ID_STRINGS})
       if("${info}" MATCHES "INFO:compiler\\[([^]\"]*)\\]")
@@ -433,6 +443,13 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
         string(REGEX REPLACE "^0+([0-9])" "\\1" COMPILER_VERSION "${CMAKE_MATCH_1}")
         string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION "${COMPILER_VERSION}")
       endif()
+      if("${info}" MATCHES "INFO:compiler_version_([A-Z]+)_digit_([0-9])\\[([0-9])\\]")
+        set(comp ${CMAKE_MATCH_1})
+        set(digit ${CMAKE_MATCH_2})
+        set(value ${CMAKE_MATCH_3})
+        math(EXPR COMPILER_VERSION_${comp} "${COMPILER_VERSION_${comp}} + ${value} * ${DIGIT_VALUE_${digit}}")
+        set(HAVE_COMPILER_VERSION_${comp} 1)
+      endif()
       if("${info}" MATCHES "INFO:simulate\\[([^]\"]*)\\]")
         set(SIMULATE_ID "${CMAKE_MATCH_1}")
       endif()
@@ -445,6 +462,17 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
       endif()
     endforeach()
 
+    # Construct compiler version from components if needed.
+    if(NOT DEFINED COMPILER_VERSION AND HAVE_COMPILER_VERSION_MAJOR)
+      set(COMPILER_VERSION "${COMPILER_VERSION_MAJOR}")
+      if(HAVE_COMPILER_VERSION_MINOR)
+        set(COMPILER_VERSION "${COMPILER_VERSION}.${COMPILER_VERSION_MINOR}")
+        if(HAVE_COMPILER_VERSION_PATCH)
+          set(COMPILER_VERSION "${COMPILER_VERSION}.${COMPILER_VERSION_PATCH}")
+        endif()
+      endif()
+    endif()
+
     # Detect the exact architecture from the PE header.
     if(WIN32)
       # The offset to the PE signature is stored at 0x3c.
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index a4bb86c..7f18d29 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -119,6 +119,47 @@ if(NOT CMAKE_Fortran_COMPILER_ID_RUN)
   set(CMAKE_Fortran_COMPILER_ID_VENDOR_FLAGS_NAG "-V")
   set(CMAKE_Fortran_COMPILER_ID_VENDOR_REGEX_NAG "NAG Fortran Compiler")
 
+  set(_version_info "")
+  foreach(m MAJOR MINOR PATCH)
+    set(_COMP "_${m}")
+    set(_version_info "${_version_info}
+#if defined(COMPILER_VERSION${_COMP})")
+    foreach(d 1 2 3 4)
+      set(_version_info "${_version_info}
+# undef DEC
+# undef HEX
+# define DEC(n) DEC_${d}(n)
+# define HEX(n) HEX_${d}(n)
+# if COMPILER_VERSION${_COMP} == 0
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[0]'
+# elif COMPILER_VERSION${_COMP} == 1
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[1]'
+# elif COMPILER_VERSION${_COMP} == 2
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[2]'
+# elif COMPILER_VERSION${_COMP} == 3
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[3]'
+# elif COMPILER_VERSION${_COMP} == 4
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[4]'
+# elif COMPILER_VERSION${_COMP} == 5
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[5]'
+# elif COMPILER_VERSION${_COMP} == 6
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[6]'
+# elif COMPILER_VERSION${_COMP} == 7
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[7]'
+# elif COMPILER_VERSION${_COMP} == 8
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[8]'
+# elif COMPILER_VERSION${_COMP} == 9
+        PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[9]'
+# endif
+")
+    endforeach()
+    set(_version_info "${_version_info}
+#endif")
+  endforeach()
+  set(CMAKE_Fortran_COMPILER_ID_VERSION_INFO "${_version_info}")
+  unset(_version_info)
+  unset(_COMP)
+
   # Try to identify the compiler.
   set(CMAKE_Fortran_COMPILER_ID)
   include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in
index 5349505..3244824 100644
--- a/Modules/CMakeFortranCompilerId.F.in
+++ b/Modules/CMakeFortranCompilerId.F.in
@@ -34,6 +34,11 @@
         PRINT *, 'INFO:compiler[Absoft]'
 #elif defined(__GNUC__)
         PRINT *, 'INFO:compiler[GNU]'
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# if defined(__GNUC_PATCHLEVEL__)
+#  define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
 #elif defined(__IBMC__)
 # if defined(__COMPILER_VER__)
         PRINT *, 'INFO:compiler[zOS]'
@@ -134,4 +139,18 @@
         PRINT *, 'INFO:arch[X86]'
 # endif
 #endif
+
+#if 0
+! Encode compiler version digits
+#endif
+#define DEC_4(n) (((n) / 1000) % 10)
+#define DEC_3(n) (((n) / 100)  % 10)
+#define DEC_2(n) (((n) / 10)   % 10)
+#define DEC_1(n) (((n)    )    % 10)
+#define HEX_4(n) ((n)>>12 & 0xF)
+#define HEX_3(n) ((n)>>8  & 0xF)
+#define HEX_2(n) ((n)>>4  & 0xF)
+#define HEX_1(n) ((n)     & 0xF)
+@CMAKE_Fortran_COMPILER_ID_VERSION_INFO@
+
       END
-- 
2.1.4

