# 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}")