1# Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2# file Copyright.txt or https://cmake.org/licensing for details. 3 4configure_file(${FortranCInterface_SOURCE_DIR}/Input.cmake.in 5 ${FortranCInterface_BINARY_DIR}/Input.cmake @ONLY) 6 7# Detect the Fortran/C interface on the first run or when the 8# configuration changes. 9if(NOT EXISTS ${FortranCInterface_BINARY_DIR}/Output.cmake 10 OR NOT EXISTS ${FortranCInterface_BINARY_DIR}/Input.cmake 11 OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake 12 IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Input.cmake 13 OR NOT ${FortranCInterface_SOURCE_DIR}/Output.cmake 14 IS_NEWER_THAN ${FortranCInterface_SOURCE_DIR}/Output.cmake.in 15 OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake 16 IS_NEWER_THAN ${FortranCInterface_SOURCE_DIR}/CMakeLists.txt 17 OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake 18 IS_NEWER_THAN ${CMAKE_CURRENT_LIST_FILE} 19 ) 20 message(CHECK_START "Detecting Fortran/C Interface") 21else() 22 return() 23endif() 24 25# Invalidate verification results. 26unset(FortranCInterface_VERIFIED_C CACHE) 27unset(FortranCInterface_VERIFIED_CXX CACHE) 28 29set(_result) 30 31cmake_policy(GET CMP0056 _FortranCInterface_CMP0056) 32if(_FortranCInterface_CMP0056 STREQUAL "NEW") 33 set(_FortranCInterface_EXE_LINKER_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS}") 34else() 35 set(_FortranCInterface_EXE_LINKER_FLAGS "") 36endif() 37unset(_FortranCInterface_CMP0056) 38 39# Build a sample project which reports symbols. 40set(CMAKE_TRY_COMPILE_CONFIGURATION Release) 41try_compile(FortranCInterface_COMPILED 42 ${FortranCInterface_BINARY_DIR} 43 ${FortranCInterface_SOURCE_DIR} 44 FortranCInterface # project name 45 FortranCInterface # target name 46 CMAKE_FLAGS 47 "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}" 48 "-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}" 49 "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE}" 50 "-DCMAKE_Fortran_FLAGS_RELEASE:STRING=${CMAKE_Fortran_FLAGS_RELEASE}" 51 ${_FortranCInterface_EXE_LINKER_FLAGS} 52 OUTPUT_VARIABLE FortranCInterface_OUTPUT) 53set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED}) 54unset(FortranCInterface_COMPILED CACHE) 55unset(_FortranCInterface_EXE_LINKER_FLAGS) 56 57# Locate the sample project executable. 58set(FortranCInterface_EXE) 59if(FortranCInterface_COMPILED) 60 include(${FortranCInterface_BINARY_DIR}/exe-Release.cmake OPTIONAL) 61else() 62 set(_result "Failed to compile") 63 file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 64 "Fortran/C interface test project failed with the following output:\n" 65 "${FortranCInterface_OUTPUT}\n") 66endif() 67 68# Load symbols from INFO:symbol[] strings in the executable. 69set(FortranCInterface_SYMBOLS) 70if(FortranCInterface_EXE) 71 file(STRINGS "${FortranCInterface_EXE}" _info_strings 72 LIMIT_COUNT 8 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]") 73 foreach(info ${_info_strings}) 74 if("${info}" MATCHES "INFO:symbol\\[([^]]*)\\]") 75 list(APPEND FortranCInterface_SYMBOLS ${CMAKE_MATCH_1}) 76 endif() 77 endforeach() 78elseif(NOT _result) 79 set(_result "Failed to load sample executable") 80endif() 81 82set(_case_mysub "LOWER") 83set(_case_my_sub "LOWER") 84set(_case_MYSUB "UPPER") 85set(_case_MY_SUB "UPPER") 86set(_global_regex "^(_*)(mysub|MYSUB)([_$]*)$") 87set(_global__regex "^(_*)(my_sub|MY_SUB)([_$]*)$") 88set(_module_regex "^(_*)(mymodule|MYMODULE)([A-Za-z_$]*)(mysub|MYSUB)([_$]*)$") 89set(_module__regex "^(_*)(my_module|MY_MODULE)([A-Za-z_$]*)(my_sub|MY_SUB)([_$]*)$") 90 91# Parse the symbol names. 92foreach(symbol ${FortranCInterface_SYMBOLS}) 93 foreach(form "" "_") 94 # Look for global symbols. 95 string(REGEX REPLACE "${_global_${form}regex}" 96 "\\1;\\2;\\3" pieces "${symbol}") 97 list(LENGTH pieces len) 98 if(len EQUAL 3) 99 set(FortranCInterface_GLOBAL_${form}SYMBOL "${symbol}") 100 list(GET pieces 0 FortranCInterface_GLOBAL_${form}PREFIX) 101 list(GET pieces 1 name) 102 list(GET pieces 2 FortranCInterface_GLOBAL_${form}SUFFIX) 103 set(FortranCInterface_GLOBAL_${form}CASE "${_case_${name}}") 104 endif() 105 106 # Look for module symbols. 107 string(REGEX REPLACE "${_module_${form}regex}" 108 "\\1;\\2;\\3;\\4;\\5" pieces "${symbol}") 109 list(LENGTH pieces len) 110 if(len EQUAL 5) 111 set(FortranCInterface_MODULE_${form}SYMBOL "${symbol}") 112 list(GET pieces 0 FortranCInterface_MODULE_${form}PREFIX) 113 list(GET pieces 1 module) 114 list(GET pieces 2 FortranCInterface_MODULE_${form}MIDDLE) 115 list(GET pieces 3 name) 116 list(GET pieces 4 FortranCInterface_MODULE_${form}SUFFIX) 117 set(FortranCInterface_MODULE_${form}CASE "${_case_${name}}") 118 endif() 119 endforeach() 120endforeach() 121 122# Construct mangling macro definitions. 123set(_name_LOWER "name") 124set(_name_UPPER "NAME") 125foreach(form "" "_") 126 if(FortranCInterface_GLOBAL_${form}SYMBOL) 127 if(FortranCInterface_GLOBAL_${form}PREFIX) 128 set(_prefix "${FortranCInterface_GLOBAL_${form}PREFIX}##") 129 else() 130 set(_prefix "") 131 endif() 132 if(FortranCInterface_GLOBAL_${form}SUFFIX) 133 set(_suffix "##${FortranCInterface_GLOBAL_${form}SUFFIX}") 134 else() 135 set(_suffix "") 136 endif() 137 set(_name "${_name_${FortranCInterface_GLOBAL_${form}CASE}}") 138 set(FortranCInterface_GLOBAL${form}_MACRO 139 "(name,NAME) ${_prefix}${_name}${_suffix}") 140 endif() 141 if(FortranCInterface_MODULE_${form}SYMBOL) 142 if(FortranCInterface_MODULE_${form}PREFIX) 143 set(_prefix "${FortranCInterface_MODULE_${form}PREFIX}##") 144 else() 145 set(_prefix "") 146 endif() 147 if(FortranCInterface_MODULE_${form}SUFFIX) 148 set(_suffix "##${FortranCInterface_MODULE_${form}SUFFIX}") 149 else() 150 set(_suffix "") 151 endif() 152 set(_name "${_name_${FortranCInterface_MODULE_${form}CASE}}") 153 set(_middle "##${FortranCInterface_MODULE_${form}MIDDLE}##") 154 set(FortranCInterface_MODULE${form}_MACRO 155 "(mod_name,name, mod_NAME,NAME) ${_prefix}mod_${_name}${_middle}${_name}${_suffix}") 156 endif() 157endforeach() 158 159# Summarize what is available. 160foreach(scope GLOBAL MODULE) 161 if(FortranCInterface_${scope}_SYMBOL AND 162 FortranCInterface_${scope}__SYMBOL) 163 set(FortranCInterface_${scope}_FOUND 1) 164 else() 165 set(FortranCInterface_${scope}_FOUND 0) 166 endif() 167endforeach() 168 169# Record the detection results. 170configure_file(${FortranCInterface_SOURCE_DIR}/Output.cmake.in 171 ${FortranCInterface_BINARY_DIR}/Output.cmake @ONLY) 172file(APPEND ${FortranCInterface_BINARY_DIR}/Output.cmake "\n") 173 174# Report the results. 175if(FortranCInterface_GLOBAL_FOUND) 176 if(FortranCInterface_MODULE_FOUND) 177 set(_result "Found GLOBAL and MODULE mangling") 178 else() 179 set(_result "Found GLOBAL but not MODULE mangling") 180 endif() 181 set(_result_type CHECK_PASS) 182elseif(NOT _result) 183 set(_result "Failed to recognize symbols") 184 set(_result_type CHECK_FAIL) 185endif() 186message(${_result_type} "${_result}") 187