Browse Source

FindOpenMP: Detect version (specification date) from compiler

Port changes from VTK commit fda6a31cb9 (Added Improved FindOpenMP
module, 2015-04-23).  Improve use of try_compile to avoid needing
to pass OpenMP flags as libraries.
Sujin Philip 9 years ago
parent
commit
73e9f36ea6
2 changed files with 107 additions and 0 deletions
  1. 5 0
      Help/release/dev/FindOpenMP-updates.rst
  2. 102 0
      Modules/FindOpenMP.cmake

+ 5 - 0
Help/release/dev/FindOpenMP-updates.rst

@@ -0,0 +1,5 @@
+FindOpenMP-updates
+------------------
+
+* The :module:`FindOpenMP` module learned to detect the OpenMP
+  version (specification date) from the compiler.

+ 102 - 0
Modules/FindOpenMP.cmake

@@ -20,6 +20,19 @@
 #   Flags to add to the Fortran compiler for OpenMP support.
 # ``OPENMP_FOUND``
 #   True if openmp is detected.
+#
+# The following internal variables are set, if detected:
+#
+# ``OpenMP_C_SPEC_DATE``
+#   Specification date of OpenMP version of C compiler.
+# ``OpenMP_CXX_SPEC_DATE``
+#   Specification date of OpenMP version of CXX compiler.
+# ``OpenMP_Fortran_SPEC_DATE``
+#   Specification date of OpenMP version of Fortran compiler.
+#
+# The specification dates are formatted as integers of the form
+# ``CCYYMM`` where these represent the decimal digits of the century,
+# year, and month.
 
 #=============================================================================
 # Copyright 2009 Kitware, Inc.
@@ -119,6 +132,75 @@ set(OpenMP_Fortran_TEST_SOURCE
   "
   )
 
+set(OpenMP_C_CXX_CHECK_VERSION_SOURCE
+"
+#include <stdio.h>
+#include <omp.h>
+const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M',
+                            'P', '-', 'd', 'a', 't', 'e', '[',
+                            ('0' + ((_OPENMP/100000)%10)),
+                            ('0' + ((_OPENMP/10000)%10)),
+                            ('0' + ((_OPENMP/1000)%10)),
+                            ('0' + ((_OPENMP/100)%10)),
+                            ('0' + ((_OPENMP/10)%10)),
+                            ('0' + ((_OPENMP/1)%10)),
+                            ']', '\\0' };
+int main(int argc, char *argv[])
+{
+  printf(\"%s\\n\", ompver_str);
+  return 0;
+}
+")
+
+set(OpenMP_Fortran_CHECK_VERSION_SOURCE
+"
+      program omp_ver
+      use omp_lib
+      integer, parameter :: zero = ichar('0')
+      integer, parameter :: ompv = openmp_version
+      character, dimension(24), parameter :: ompver_str =&
+      (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 'P', '-',&
+         'd', 'a', 't', 'e', '[',&
+         char(zero + mod(ompv/100000, 10)),&
+         char(zero + mod(ompv/10000, 10)),&
+         char(zero + mod(ompv/1000, 10)),&
+         char(zero + mod(ompv/100, 10)),&
+         char(zero + mod(ompv/10, 10)),&
+         char(zero + mod(ompv/1, 10)), ']' /)
+      print *, ompver_str
+      end program omp_ver
+")
+
+function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
+  set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP)
+  if("${LANG}" STREQUAL "C")
+    set(SRC_FILE ${WORK_DIR}/ompver.c)
+    file(WRITE ${SRC_FILE} "${OpenMP_C_CXX_CHECK_VERSION_SOURCE}")
+  elseif("${LANG}" STREQUAL "CXX")
+    set(SRC_FILE ${WORK_DIR}/ompver.cpp)
+    file(WRITE ${SRC_FILE} "${OpenMP_C_CXX_CHECK_VERSION_SOURCE}")
+  else() # ("${LANG}" STREQUAL "Fortran")
+    set(SRC_FILE ${WORK_DIR}/ompver.f90)
+    file(WRITE ${SRC_FILE} "${OpenMP_Fortran_CHECK_VERSION_SOURCE}")
+  endif()
+
+  set(BIN_FILE ${WORK_DIR}/ompver_${LANG}.bin)
+  try_compile(OpenMP_TRY_COMPILE_RESULT ${CMAKE_BINARY_DIR} ${SRC_FILE}
+              CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}"
+              COPY_FILE ${BIN_FILE})
+
+  if(${OpenMP_TRY_COMPILE_RESULT})
+    file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
+    set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*")
+    if("${specstr}" MATCHES "${regex_spec_date}")
+      set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
+    endif()
+  endif()
+
+  unset(OpenMP_TRY_COMPILE_RESULT CACHE)
+endfunction()
+
+
 # check c compiler
 if(CMAKE_C_COMPILER_LOADED)
   # if these are set then do not try to find them again,
@@ -150,6 +232,12 @@ if(CMAKE_C_COMPILER_LOADED)
 
   list(APPEND _OPENMP_REQUIRED_VARS OpenMP_C_FLAGS)
   unset(OpenMP_C_FLAG_CANDIDATES)
+
+  if (NOT OpenMP_C_SPEC_DATE)
+    _OPENMP_GET_SPEC_DATE("C" OpenMP_C_SPEC_DATE_INTERNAL)
+    set(OpenMP_C_SPEC_DATE "${OpenMP_C_SPEC_DATE_INTERNAL}" CACHE
+      INTERNAL "C compiler's OpenMP specification date")
+  endif()
 endif()
 
 # check cxx compiler
@@ -186,6 +274,12 @@ if(CMAKE_CXX_COMPILER_LOADED)
 
   list(APPEND _OPENMP_REQUIRED_VARS OpenMP_CXX_FLAGS)
   unset(OpenMP_CXX_FLAG_CANDIDATES)
+
+  if (NOT OpenMP_CXX_SPEC_DATE)
+    _OPENMP_GET_SPEC_DATE("CXX" OpenMP_CXX_SPEC_DATE_INTERNAL)
+    set(OpenMP_CXX_SPEC_DATE "${OpenMP_CXX_SPEC_DATE_INTERNAL}" CACHE
+      INTERNAL "C++ compiler's OpenMP specification date")
+  endif()
 endif()
 
 # check Fortran compiler
@@ -219,6 +313,12 @@ if(CMAKE_Fortran_COMPILER_LOADED)
 
   list(APPEND _OPENMP_REQUIRED_VARS OpenMP_Fortran_FLAGS)
   unset(OpenMP_Fortran_FLAG_CANDIDATES)
+
+  if (NOT OpenMP_Fortran_SPEC_DATE)
+    _OPENMP_GET_SPEC_DATE("Fortran" OpenMP_Fortran_SPEC_DATE_INTERNAL)
+    set(OpenMP_Fortran_SPEC_DATE "${OpenMP_Fortran_SPEC_DATE_INTERNAL}" CACHE
+      INTERNAL "Fortran compiler's OpenMP specification date")
+  endif()
 endif()
 
 set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE})
@@ -239,3 +339,5 @@ endif()
 unset(OpenMP_C_TEST_SOURCE)
 unset(OpenMP_CXX_TEST_SOURCE)
 unset(OpenMP_Fortran_TEST_SOURCE)
+unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE)
+unset(OpenMP_Fortran_CHECK_VERSION_SOURCE)