| # 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 |
| PROJECT FortranCInterface |
| TARGET FortranCInterface |
| SOURCE_DIR ${FortranCInterface_SOURCE_DIR} |
| BINARY_DIR ${FortranCInterface_BINARY_DIR} |
| 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 "^(_*)([A-Za-z$]*)(mymodule|MYMODULE)([A-Za-z_$]*)(mysub|MYSUB)([_$]*)$") |
| set(_module__regex "^(_*)([A-Za-z$]*)(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;\\6" 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}") |