Fortran: Add infrastructure to detect compiler version (#15372)

Fortran does not offer syntax to compose a string literal at
preprocessing time from numeric compuations.  Instead encode each digit
of each component as a separate INFO string and compose them in CMake
code after extraction.  Support MAJOR, MINOR, PATCH, and TWEAK
components with up to 8 digits each.
This commit is contained in:
Brad King 2015-02-17 13:24:31 -05:00
parent ec1ec47193
commit e6ebc814df
3 changed files with 103 additions and 1 deletions

View File

@ -409,12 +409,28 @@ 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(COMPILER_VERSION_TWEAK 0)
set(HAVE_COMPILER_VERSION_MAJOR 0)
set(HAVE_COMPILER_VERSION_MINOR 0)
set(HAVE_COMPILER_VERSION_PATCH 0)
set(HAVE_COMPILER_VERSION_TWEAK 0)
set(DIGIT_VALUE_1 1)
set(DIGIT_VALUE_2 10)
set(DIGIT_VALUE_3 100)
set(DIGIT_VALUE_4 1000)
set(DIGIT_VALUE_5 10000)
set(DIGIT_VALUE_6 100000)
set(DIGIT_VALUE_7 1000000)
set(DIGIT_VALUE_8 10000000)
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 38 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
set(COMPILER_ID_TWICE)
foreach(info ${CMAKE_${lang}_COMPILER_ID_STRINGS})
if("${info}" MATCHES "INFO:compiler\\[([^]\"]*)\\]")
@ -433,6 +449,15 @@ 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()
foreach(comp MAJOR MINOR PATCH TWEAK)
foreach(digit 1 2 3 4 5 6 7 8 9)
if("${info}" MATCHES "INFO:compiler_version_${comp}_digit_${digit}\\[([0-9])\\]")
set(value ${CMAKE_MATCH_1})
math(EXPR COMPILER_VERSION_${comp} "${COMPILER_VERSION_${comp}} + ${value} * ${DIGIT_VALUE_${digit}}")
set(HAVE_COMPILER_VERSION_${comp} 1)
endif()
endforeach()
endforeach()
if("${info}" MATCHES "INFO:simulate\\[([^]\"]*)\\]")
set(SIMULATE_ID "${CMAKE_MATCH_1}")
endif()
@ -445,6 +470,20 @@ 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}")
if(HAVE_COMPILER_VERSION_TWEAK)
set(COMPILER_VERSION "${COMPILER_VERSION}.${COMPILER_VERSION_TWEAK}")
endif()
endif()
endif()
endif()
# Detect the exact architecture from the PE header.
if(WIN32)
# The offset to the PE signature is stored at 0x3c.

View File

@ -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 TWEAK)
set(_COMP "_${m}")
set(_version_info "${_version_info}
#if defined(COMPILER_VERSION${_COMP})")
foreach(d 1 2 3 4 5 6 7 8)
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)

View File

@ -134,4 +134,26 @@
PRINT *, 'INFO:arch[X86]'
# endif
#endif
#if 0
! Encode compiler version digits
#endif
#define DEC_8(n) (((n) / 10000000) % 10)
#define DEC_7(n) (((n) / 1000000) % 10)
#define DEC_6(n) (((n) / 100000) % 10)
#define DEC_5(n) (((n) / 10000) % 10)
#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_8(n) ((n)>>28 & 0xF)
#define HEX_7(n) ((n)>>24 & 0xF)
#define HEX_6(n) ((n)>>20 & 0xF)
#define HEX_5(n) ((n)>>16 & 0xF)
#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