Detect.cmake 6.5 KB

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