| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| # file Copyright.txt or https://cmake.org/licensing for details. | |
| configure_file(${FortranCInterface_SOURCE_DIR}/Input.cmake.in | |
| ${FortranCInterface_BINARY_DIR}/Input.cmake @ONLY) | |
| # Detect the Fortran/C interface on the first run or when the | |
| # configuration changes. | |
| if(NOT EXISTS ${FortranCInterface_BINARY_DIR}/Output.cmake | |
| OR NOT EXISTS ${FortranCInterface_BINARY_DIR}/Input.cmake | |
| OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake | |
| IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Input.cmake | |
| OR NOT ${FortranCInterface_SOURCE_DIR}/Output.cmake | |
| IS_NEWER_THAN ${FortranCInterface_SOURCE_DIR}/Output.cmake.in | |
| OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake | |
| IS_NEWER_THAN ${FortranCInterface_SOURCE_DIR}/CMakeLists.txt | |
| OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake | |
| IS_NEWER_THAN ${CMAKE_CURRENT_LIST_FILE} | |
| ) | |
| message(CHECK_START "Detecting Fortran/C Interface") | |
| else() | |
| return() | |
| endif() | |
| # Invalidate verification results. | |
| unset(FortranCInterface_VERIFIED_C CACHE) | |
| unset(FortranCInterface_VERIFIED_CXX CACHE) | |
| set(_result) | |
| # Perform detection with only one architecture so that | |
| # the info strings are not repeated. | |
| if(CMAKE_OSX_ARCHITECTURES MATCHES "^([^;]+)(;|$)") | |
| set(_FortranCInterface_OSX_ARCH "-DCMAKE_OSX_ARCHITECTURES=${CMAKE_MATCH_1}") | |
| else() | |
| set(_FortranCInterface_OSX_ARCH "") | |
| endif() | |
| cmake_policy(GET CMP0056 _FortranCInterface_CMP0056) | |
| if(_FortranCInterface_CMP0056 STREQUAL "NEW") | |
| set(_FortranCInterface_EXE_LINKER_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS}") | |
| else() | |
| set(_FortranCInterface_EXE_LINKER_FLAGS "") | |
| endif() | |
| unset(_FortranCInterface_CMP0056) | |
| # Build a sample project which reports symbols. | |
| set(CMAKE_TRY_COMPILE_CONFIGURATION Release) | |
| try_compile(FortranCInterface_COMPILED | |
| ${FortranCInterface_BINARY_DIR} | |
| ${FortranCInterface_SOURCE_DIR} | |
| FortranCInterface # project name | |
| FortranCInterface # target name | |
| CMAKE_FLAGS | |
| "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}" | |
| "-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}" | |
| "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE}" | |
| "-DCMAKE_Fortran_FLAGS_RELEASE:STRING=${CMAKE_Fortran_FLAGS_RELEASE}" | |
| ${_FortranCInterface_OSX_ARCH} | |
| ${_FortranCInterface_EXE_LINKER_FLAGS} | |
| OUTPUT_VARIABLE FortranCInterface_OUTPUT) | |
| set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED}) | |
| unset(FortranCInterface_COMPILED CACHE) | |
| unset(_FortranCInterface_EXE_LINKER_FLAGS) | |
| unset(_FortranCInterface_OSX_ARCH) | |
| # Locate the sample project executable. | |
| set(FortranCInterface_EXE) | |
| if(FortranCInterface_COMPILED) | |
| include(${FortranCInterface_BINARY_DIR}/exe-Release.cmake OPTIONAL) | |
| else() | |
| set(_result "Failed to compile") | |
| file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log | |
| "Fortran/C interface test project failed with the following output:\n" | |
| "${FortranCInterface_OUTPUT}\n") | |
| endif() | |
| # Load symbols from INFO:symbol[] strings in the executable. | |
| set(FortranCInterface_SYMBOLS) | |
| if(FortranCInterface_EXE) | |
| file(STRINGS "${FortranCInterface_EXE}" _info_strings | |
| LIMIT_COUNT 8 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]") | |
| foreach(info ${_info_strings}) | |
| if("${info}" MATCHES "INFO:symbol\\[([^]]*)\\]") | |
| list(APPEND FortranCInterface_SYMBOLS ${CMAKE_MATCH_1}) | |
| endif() | |
| endforeach() | |
| elseif(NOT _result) | |
| set(_result "Failed to load sample executable") | |
| endif() | |
| set(_case_mysub "LOWER") | |
| set(_case_my_sub "LOWER") | |
| set(_case_MYSUB "UPPER") | |
| set(_case_MY_SUB "UPPER") | |
| set(_global_regex "^(_*)(mysub|MYSUB)([_$]*)$") | |
| set(_global__regex "^(_*)(my_sub|MY_SUB)([_$]*)$") | |
| set(_module_regex "^(_*)(mymodule|MYMODULE)([A-Za-z_$]*)(mysub|MYSUB)([_$]*)$") | |
| set(_module__regex "^(_*)(my_module|MY_MODULE)([A-Za-z_$]*)(my_sub|MY_SUB)([_$]*)$") | |
| # Parse the symbol names. | |
| foreach(symbol ${FortranCInterface_SYMBOLS}) | |
| foreach(form "" "_") | |
| # Look for global symbols. | |
| string(REGEX REPLACE "${_global_${form}regex}" | |
| "\\1;\\2;\\3" pieces "${symbol}") | |
| list(LENGTH pieces len) | |
| if(len EQUAL 3) | |
| set(FortranCInterface_GLOBAL_${form}SYMBOL "${symbol}") | |
| list(GET pieces 0 FortranCInterface_GLOBAL_${form}PREFIX) | |
| list(GET pieces 1 name) | |
| list(GET pieces 2 FortranCInterface_GLOBAL_${form}SUFFIX) | |
| set(FortranCInterface_GLOBAL_${form}CASE "${_case_${name}}") | |
| endif() | |
| # Look for module symbols. | |
| string(REGEX REPLACE "${_module_${form}regex}" | |
| "\\1;\\2;\\3;\\4;\\5" pieces "${symbol}") | |
| list(LENGTH pieces len) | |
| if(len EQUAL 5) | |
| set(FortranCInterface_MODULE_${form}SYMBOL "${symbol}") | |
| list(GET pieces 0 FortranCInterface_MODULE_${form}PREFIX) | |
| list(GET pieces 1 module) | |
| list(GET pieces 2 FortranCInterface_MODULE_${form}MIDDLE) | |
| list(GET pieces 3 name) | |
| list(GET pieces 4 FortranCInterface_MODULE_${form}SUFFIX) | |
| set(FortranCInterface_MODULE_${form}CASE "${_case_${name}}") | |
| endif() | |
| endforeach() | |
| endforeach() | |
| # Construct mangling macro definitions. | |
| set(_name_LOWER "name") | |
| set(_name_UPPER "NAME") | |
| foreach(form "" "_") | |
| if(FortranCInterface_GLOBAL_${form}SYMBOL) | |
| if(FortranCInterface_GLOBAL_${form}PREFIX) | |
| set(_prefix "${FortranCInterface_GLOBAL_${form}PREFIX}##") | |
| else() | |
| set(_prefix "") | |
| endif() | |
| if(FortranCInterface_GLOBAL_${form}SUFFIX) | |
| set(_suffix "##${FortranCInterface_GLOBAL_${form}SUFFIX}") | |
| else() | |
| set(_suffix "") | |
| endif() | |
| set(_name "${_name_${FortranCInterface_GLOBAL_${form}CASE}}") | |
| set(FortranCInterface_GLOBAL${form}_MACRO | |
| "(name,NAME) ${_prefix}${_name}${_suffix}") | |
| endif() | |
| if(FortranCInterface_MODULE_${form}SYMBOL) | |
| if(FortranCInterface_MODULE_${form}PREFIX) | |
| set(_prefix "${FortranCInterface_MODULE_${form}PREFIX}##") | |
| else() | |
| set(_prefix "") | |
| endif() | |
| if(FortranCInterface_MODULE_${form}SUFFIX) | |
| set(_suffix "##${FortranCInterface_MODULE_${form}SUFFIX}") | |
| else() | |
| set(_suffix "") | |
| endif() | |
| set(_name "${_name_${FortranCInterface_MODULE_${form}CASE}}") | |
| set(_middle "##${FortranCInterface_MODULE_${form}MIDDLE}##") | |
| set(FortranCInterface_MODULE${form}_MACRO | |
| "(mod_name,name, mod_NAME,NAME) ${_prefix}mod_${_name}${_middle}${_name}${_suffix}") | |
| endif() | |
| endforeach() | |
| # Summarize what is available. | |
| foreach(scope GLOBAL MODULE) | |
| if(FortranCInterface_${scope}_SYMBOL AND | |
| FortranCInterface_${scope}__SYMBOL) | |
| set(FortranCInterface_${scope}_FOUND 1) | |
| else() | |
| set(FortranCInterface_${scope}_FOUND 0) | |
| endif() | |
| endforeach() | |
| # Record the detection results. | |
| configure_file(${FortranCInterface_SOURCE_DIR}/Output.cmake.in | |
| ${FortranCInterface_BINARY_DIR}/Output.cmake @ONLY) | |
| file(APPEND ${FortranCInterface_BINARY_DIR}/Output.cmake "\n") | |
| # Report the results. | |
| if(FortranCInterface_GLOBAL_FOUND) | |
| if(FortranCInterface_MODULE_FOUND) | |
| set(_result "Found GLOBAL and MODULE mangling") | |
| else() | |
| set(_result "Found GLOBAL but not MODULE mangling") | |
| endif() | |
| set(_result_type CHECK_PASS) | |
| elseif(NOT _result) | |
| set(_result "Failed to recognize symbols") | |
| set(_result_type CHECK_FAIL) | |
| endif() | |
| message(${_result_type} "${_result}") |