1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
4 configure_file(${FortranCInterface_SOURCE_DIR}/Input.cmake.in
5 ${FortranCInterface_BINARY_DIR}/Input.cmake @ONLY)
7 # Detect the Fortran/C interface on the first run or when the
8 # configuration changes.
9 if(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}
20 message(CHECK_START "Detecting Fortran/C Interface")
25 # Invalidate verification results.
26 unset(FortranCInterface_VERIFIED_C CACHE)
27 unset(FortranCInterface_VERIFIED_CXX CACHE)
31 cmake_policy(GET CMP0056 _FortranCInterface_CMP0056)
32 if(_FortranCInterface_CMP0056 STREQUAL "NEW")
33 set(_FortranCInterface_EXE_LINKER_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS}")
35 set(_FortranCInterface_EXE_LINKER_FLAGS "")
37 unset(_FortranCInterface_CMP0056)
39 # Build a sample project which reports symbols.
40 set(CMAKE_TRY_COMPILE_CONFIGURATION Release)
41 try_compile(FortranCInterface_COMPILED
42 ${FortranCInterface_BINARY_DIR}
43 ${FortranCInterface_SOURCE_DIR}
44 FortranCInterface # project name
45 FortranCInterface # target name
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)
53 set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED})
54 unset(FortranCInterface_COMPILED CACHE)
55 unset(_FortranCInterface_EXE_LINKER_FLAGS)
57 # Locate the sample project executable.
58 set(FortranCInterface_EXE)
59 if(FortranCInterface_COMPILED)
60 include(${FortranCInterface_BINARY_DIR}/exe-Release.cmake OPTIONAL)
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")
68 # Load symbols from INFO:symbol[] strings in the executable.
69 set(FortranCInterface_SYMBOLS)
70 if(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})
79 set(_result "Failed to load sample executable")
82 set(_case_mysub "LOWER")
83 set(_case_my_sub "LOWER")
84 set(_case_MYSUB "UPPER")
85 set(_case_MY_SUB "UPPER")
86 set(_global_regex "^(_*)(mysub|MYSUB)([_$]*)$")
87 set(_global__regex "^(_*)(my_sub|MY_SUB)([_$]*)$")
88 set(_module_regex "^(_*)(mymodule|MYMODULE)([A-Za-z_$]*)(mysub|MYSUB)([_$]*)$")
89 set(_module__regex "^(_*)(my_module|MY_MODULE)([A-Za-z_$]*)(my_sub|MY_SUB)([_$]*)$")
91 # Parse the symbol names.
92 foreach(symbol ${FortranCInterface_SYMBOLS})
94 # Look for global symbols.
95 string(REGEX REPLACE "${_global_${form}regex}"
96 "\\1;\\2;\\3" pieces "${symbol}")
97 list(LENGTH pieces len)
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}}")
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)
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}}")
122 # Construct mangling macro definitions.
123 set(_name_LOWER "name")
124 set(_name_UPPER "NAME")
126 if(FortranCInterface_GLOBAL_${form}SYMBOL)
127 if(FortranCInterface_GLOBAL_${form}PREFIX)
128 set(_prefix "${FortranCInterface_GLOBAL_${form}PREFIX}##")
132 if(FortranCInterface_GLOBAL_${form}SUFFIX)
133 set(_suffix "##${FortranCInterface_GLOBAL_${form}SUFFIX}")
137 set(_name "${_name_${FortranCInterface_GLOBAL_${form}CASE}}")
138 set(FortranCInterface_GLOBAL${form}_MACRO
139 "(name,NAME) ${_prefix}${_name}${_suffix}")
141 if(FortranCInterface_MODULE_${form}SYMBOL)
142 if(FortranCInterface_MODULE_${form}PREFIX)
143 set(_prefix "${FortranCInterface_MODULE_${form}PREFIX}##")
147 if(FortranCInterface_MODULE_${form}SUFFIX)
148 set(_suffix "##${FortranCInterface_MODULE_${form}SUFFIX}")
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}")
159 # Summarize what is available.
160 foreach(scope GLOBAL MODULE)
161 if(FortranCInterface_${scope}_SYMBOL AND
162 FortranCInterface_${scope}__SYMBOL)
163 set(FortranCInterface_${scope}_FOUND 1)
165 set(FortranCInterface_${scope}_FOUND 0)
169 # Record the detection results.
170 configure_file(${FortranCInterface_SOURCE_DIR}/Output.cmake.in
171 ${FortranCInterface_BINARY_DIR}/Output.cmake @ONLY)
172 file(APPEND ${FortranCInterface_BINARY_DIR}/Output.cmake "\n")
174 # Report the results.
175 if(FortranCInterface_GLOBAL_FOUND)
176 if(FortranCInterface_MODULE_FOUND)
177 set(_result "Found GLOBAL and MODULE mangling")
179 set(_result "Found GLOBAL but not MODULE mangling")
181 set(_result_type CHECK_PASS)
183 set(_result "Failed to recognize symbols")
184 set(_result_type CHECK_FAIL)
186 message(${_result_type} "${_result}")