1###############################################################################
2# checks
3set(Fortran_FEATURE_CHECK_DIR ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "fortran file directory")
4
5MACRO(fortran_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
6  IF (NOT DEFINED ${RESULT_VAR})
7    SET(_bindir "${CMAKE_BINARY_DIR}/fortran_feature_tests/fortran_${FEATURE_NAME}")
8
9    IF (${FEATURE_NUMBER})
10      SET(_SRCFILE_BASE ${Fortran_FEATURE_CHECK_DIR}/${FEATURE_NAME}-N${FEATURE_NUMBER})
11      SET(_LOG_NAME "\"${FEATURE_NAME}\" (N${FEATURE_NUMBER})")
12    ELSE (${FEATURE_NUMBER})
13      SET(_SRCFILE_BASE ${Fortran_FEATURE_CHECK_DIR}/${FEATURE_NAME})
14      SET(_LOG_NAME "\"${FEATURE_NAME}\"")
15    ENDIF (${FEATURE_NUMBER})
16    ecbuild_info("Checking Fortran support for ${_LOG_NAME}")
17
18    SET(_SRCFILE "${_SRCFILE_BASE}.F90")
19    SET(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.F90")
20    SET(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.F90")
21
22    IF (CROSS_COMPILING)
23      try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}")
24      IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
25        try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
26      ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
27    ELSE (CROSS_COMPILING)
28      ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
29          "${_bindir}" "${_SRCFILE}")
30      IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
31        SET(${RESULT_VAR} TRUE)
32      ELSE (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
33        SET(${RESULT_VAR} FALSE)
34      ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
35      IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
36        ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
37            "${_bindir}_fail" "${_SRCFILE_FAIL}")
38        IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
39          SET(${RESULT_VAR} TRUE)
40        ELSE (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
41          SET(${RESULT_VAR} FALSE)
42        ENDIF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
43      ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
44    ENDIF (CROSS_COMPILING)
45    IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
46      try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}")
47      IF (_TMP_RESULT)
48        SET(${RESULT_VAR} FALSE)
49      ELSE (_TMP_RESULT)
50        SET(${RESULT_VAR} TRUE)
51      ENDIF (_TMP_RESULT)
52    ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
53
54    IF (${RESULT_VAR})
55      ecbuild_info("Checking Fortran support for ${_LOG_NAME} -- works")
56    ELSE (${RESULT_VAR})
57      ecbuild_info("Checking Fortran support for ${_LOG_NAME} -- not supported")
58    ENDIF (${RESULT_VAR})
59    SET(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "Fortran support for ${_LOG_NAME}")
60  ENDIF (NOT DEFINED ${RESULT_VAR})
61ENDMACRO(fortran_check_single_feature)
62
63# Find list of all features
64function(fortran_find_all_features outvar)
65  FILE(GLOB ALL_Fortran_FEATURE_FILES "${Fortran_FEATURE_CHECK_DIR}/*.F90")
66  set(OUTPUT_VARIABLES)
67  foreach(filename ${ALL_Fortran_FEATURE_FILES})
68    get_filename_component(filename ${filename} NAME_WE)
69    string(REGEX REPLACE "_fail_compile" "" filename "${filename}")
70    string(REGEX REPLACE "_fail" "" filename "${filename}")
71    string(REGEX REPLACE "-N[0-9]*" "" filename "${filename}")
72    set(OUTPUT_VARIABLES ${OUTPUT_VARIABLES} ${filename})
73  endforeach()
74  list(REMOVE_DUPLICATES OUTPUT_VARIABLES)
75  set(${outvar} ${OUTPUT_VARIABLES} PARENT_SCOPE)
76endfunction()
77
78# Parses input and separates into arguments before REQUIRED and after REQUIRED.
79# Arguments before REQUIRED are OPTIONALS.
80# Arguments after REQUIRED are REQUIRED.
81# If no arguments, then sets output OPTIONALS to ALLFEATURES.
82function(parse_input_features ALLFEATURES OPTIONALS REQUIRED ERRORS)
83
84  if("${ARGN}" STREQUAL "")
85    set(${OPTIONALS} ${ALLFEATURES} PARENT_SCOPE)
86    set(${REQUIRED} "" PARENT_SCOPE)
87  else()
88    set(REQUIRED_FEATURES)
89    set(OPTIONAL_FEATURES)
90    set(UNKNOWN_FEATURES)
91    set(result_type OPTIONAL_FEATURES)
92    foreach(feature ${ARGN})
93      if(${feature} STREQUAL "REQUIRED")
94        set(result_type REQUIRED_FEATURES)
95      else()
96        list(FIND ALLFEATURES ${feature} feature_was_found)
97
98        if(feature_was_found EQUAL -1)
99          list(APPEND UNKNOWN_FEATURES ${feature})
100        else()
101          list(APPEND ${result_type} ${feature})
102        endif()
103
104      endif(${feature} STREQUAL "REQUIRED")
105    endforeach()
106
107    set(${OPTIONALS} ${OPTIONAL_FEATURES} PARENT_SCOPE)
108    set(${REQUIRED} ${REQUIRED_FEATURES} PARENT_SCOPE)
109    set(${ERRORS} ${UNKNOWN_FEATURES} PARENT_SCOPE)
110  endif("${ARGN}" STREQUAL "")
111endfunction(parse_input_features)
112
113# Figures out name and number of feature
114# then calls macro that does the work
115macro(_figure_out_fortran_feature current_feature)
116  # Find set of files that match current_feature, excepting _fail and _fail_compile.
117  file(GLOB ALL_FEATURE_FILES "${Fortran_FEATURE_CHECK_DIR}/${current_feature}*.F90")
118  foreach(filename ${ALL_FEATURE_FILES})
119    if(filename MATCHES "_fail")
120      list(REMOVE_ITEM ALL_FEATURE_FILES ${filename})
121    endif()
122  endforeach()
123
124  list(LENGTH ALL_FEATURE_FILES NFILES)
125  if(NOT ${NFILES} EQUAL 1)
126    ecbuild_critical("[Fortran] Expected to find only one feature. Found ${NFILES} -- ${ALL_FEATURE_FILES}.")
127  endif(NOT ${NFILES} EQUAL 1)
128
129  # Now we know which file corresponds to option.
130  get_filename_component(basename ${ALL_FEATURE_FILES} NAME_WE)
131  # If has feature number, extract it
132  set(number "")
133  if(basename MATCHES "-N[0-9]*$")
134    string(REGEX REPLACE "${current_feature}-N" "" number "${basename}")
135  endif()
136  # Then call macro
137  string(TOUPPER ${current_feature} UPPER_OPTIONAL)
138  set(VARNAME HAS_Fortran_${UPPER_OPTIONAL})
139  fortran_check_single_feature(${current_feature} "${number}" ${VARNAME})
140endmacro(_figure_out_fortran_feature)
141
142function(fortran_feature_check)
143
144  # find all features
145  fortran_find_all_features(ALL_Fortran_FEATURES)
146
147  # Parses input to this function.
148  parse_input_features("${ALL_Fortran_FEATURES}" OPTIONALS REQUIRED ERRORS ${ARGN})
149  if(NOT ${ERRORS} STREQUAL "")
150    ecbuild_info("[Fortran] The following features are unknown: ${ERRORS}.")
151  endif()
152
153  # Check optional features
154  foreach(current_feature ${OPTIONALS})
155    _figure_out_fortran_feature(${current_feature})
156  endforeach(current_feature ${ARGN})
157
158  # Check required features
159  foreach(current_feature ${REQUIRED})
160    _figure_out_fortran_feature(${current_feature})
161    string(TOUPPER ${current_feature} UPPER_REQUIRED)
162    set(VARNAME HAS_Fortran_${UPPER_REQUIRED})
163    if(NOT ${VARNAME})
164      ecbuild_critical("[Fortran] Required feature ${current_feature} is not available.")
165    endif(NOT ${VARNAME})
166  endforeach(current_feature ${REQUIRED})
167
168endfunction(fortran_feature_check)
169