Detect.cmake 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. OUTPUT_VARIABLE FortranCInterface_OUTPUT)
  38. set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED})
  39. unset(FortranCInterface_COMPILED CACHE)
  40. # Locate the sample project executable.
  41. if(FortranCInterface_COMPILED)
  42. find_program(FortranCInterface_EXE
  43. NAMES FortranCInterface
  44. PATHS ${FortranCInterface_BINARY_DIR} ${FortranCInterface_BINARY_DIR}/Debug
  45. NO_DEFAULT_PATH
  46. )
  47. set(FortranCInterface_EXE ${FortranCInterface_EXE})
  48. unset(FortranCInterface_EXE CACHE)
  49. else()
  50. set(_result "Failed to compile")
  51. set(FortranCInterface_EXE)
  52. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  53. "Fortran/C interface test project failed with the following output:\n"
  54. "${FortranCInterface_OUTPUT}\n")
  55. endif()
  56. # Load symbols from INFO:symbol[] strings in the executable.
  57. set(FortranCInterface_SYMBOLS)
  58. if(FortranCInterface_EXE)
  59. file(STRINGS "${FortranCInterface_EXE}" _info_strings
  60. LIMIT_COUNT 8 REGEX "INFO:[^[]*\\[")
  61. foreach(info ${_info_strings})
  62. if("${info}" MATCHES ".*INFO:symbol\\[([^]]*)\\].*")
  63. string(REGEX REPLACE ".*INFO:symbol\\[([^]]*)\\].*" "\\1" symbol "${info}")
  64. list(APPEND FortranCInterface_SYMBOLS ${symbol})
  65. endif()
  66. endforeach()
  67. elseif(NOT _result)
  68. set(_result "Failed to load sample executable")
  69. endif()
  70. set(_case_mysub "LOWER")
  71. set(_case_my_sub "LOWER")
  72. set(_case_MYSUB "UPPER")
  73. set(_case_MY_SUB "UPPER")
  74. set(_global_regex "^(_*)(mysub|MYSUB)([_$]*)$")
  75. set(_global__regex "^(_*)(my_sub|MY_SUB)([_$]*)$")
  76. set(_module_regex "^(_*)(mymodule|MYMODULE)([A-Za-z_$]*)(mysub|MYSUB)([_$]*)$")
  77. set(_module__regex "^(_*)(my_module|MY_MODULE)([A-Za-z_$]*)(my_sub|MY_SUB)([_$]*)$")
  78. # Parse the symbol names.
  79. foreach(symbol ${FortranCInterface_SYMBOLS})
  80. foreach(form "" "_")
  81. # Look for global symbols.
  82. string(REGEX REPLACE "${_global_${form}regex}"
  83. "\\1;\\2;\\3" pieces "${symbol}")
  84. list(LENGTH pieces len)
  85. if(len EQUAL 3)
  86. set(FortranCInterface_GLOBAL_${form}SYMBOL "${symbol}")
  87. list(GET pieces 0 FortranCInterface_GLOBAL_${form}PREFIX)
  88. list(GET pieces 1 name)
  89. list(GET pieces 2 FortranCInterface_GLOBAL_${form}SUFFIX)
  90. set(FortranCInterface_GLOBAL_${form}CASE "${_case_${name}}")
  91. endif()
  92. # Look for module symbols.
  93. string(REGEX REPLACE "${_module_${form}regex}"
  94. "\\1;\\2;\\3;\\4;\\5" pieces "${symbol}")
  95. list(LENGTH pieces len)
  96. if(len EQUAL 5)
  97. set(FortranCInterface_MODULE_${form}SYMBOL "${symbol}")
  98. list(GET pieces 0 FortranCInterface_MODULE_${form}PREFIX)
  99. list(GET pieces 1 module)
  100. list(GET pieces 2 FortranCInterface_MODULE_${form}MIDDLE)
  101. list(GET pieces 3 name)
  102. list(GET pieces 4 FortranCInterface_MODULE_${form}SUFFIX)
  103. set(FortranCInterface_MODULE_${form}CASE "${_case_${name}}")
  104. endif()
  105. endforeach()
  106. endforeach()
  107. # Construct mangling macro definitions.
  108. set(_name_LOWER "name")
  109. set(_name_UPPER "NAME")
  110. foreach(form "" "_")
  111. if(FortranCInterface_GLOBAL_${form}SYMBOL)
  112. if(FortranCInterface_GLOBAL_${form}PREFIX)
  113. set(_prefix "${FortranCInterface_GLOBAL_${form}PREFIX}##")
  114. else()
  115. set(_prefix "")
  116. endif()
  117. if(FortranCInterface_GLOBAL_${form}SUFFIX)
  118. set(_suffix "##${FortranCInterface_GLOBAL_${form}SUFFIX}")
  119. else()
  120. set(_suffix "")
  121. endif()
  122. set(_name "${_name_${FortranCInterface_GLOBAL_${form}CASE}}")
  123. set(FortranCInterface_GLOBAL${form}_MACRO
  124. "(name,NAME) ${_prefix}${_name}${_suffix}")
  125. endif()
  126. if(FortranCInterface_MODULE_${form}SYMBOL)
  127. if(FortranCInterface_MODULE_${form}PREFIX)
  128. set(_prefix "${FortranCInterface_MODULE_${form}PREFIX}##")
  129. else()
  130. set(_prefix "")
  131. endif()
  132. if(FortranCInterface_MODULE_${form}SUFFIX)
  133. set(_suffix "##${FortranCInterface_MODULE_${form}SUFFIX}")
  134. else()
  135. set(_suffix "")
  136. endif()
  137. set(_name "${_name_${FortranCInterface_MODULE_${form}CASE}}")
  138. set(_middle "##${FortranCInterface_MODULE_${form}MIDDLE}##")
  139. set(FortranCInterface_MODULE${form}_MACRO
  140. "(mod_name,name, mod_NAME,NAME) ${_prefix}mod_${_name}${_middle}${_name}${_suffix}")
  141. endif()
  142. endforeach()
  143. # Summarize what is available.
  144. foreach(scope GLOBAL MODULE)
  145. if(FortranCInterface_${scope}_SYMBOL AND
  146. FortranCInterface_${scope}__SYMBOL)
  147. set(FortranCInterface_${scope}_FOUND 1)
  148. else()
  149. set(FortranCInterface_${scope}_FOUND 0)
  150. endif()
  151. endforeach()
  152. # Record the detection results.
  153. configure_file(${FortranCInterface_SOURCE_DIR}/Output.cmake.in
  154. ${FortranCInterface_BINARY_DIR}/Output.cmake @ONLY)
  155. file(APPEND ${FortranCInterface_BINARY_DIR}/Output.cmake "\n")
  156. # Report the results.
  157. if(FortranCInterface_GLOBAL_FOUND)
  158. if(FortranCInterface_MODULE_FOUND)
  159. set(_result "Found GLOBAL and MODULE mangling")
  160. else(FortranCInterface_MODULE_FOUND)
  161. set(_result "Found GLOBAL but not MODULE mangling")
  162. endif()
  163. elseif(NOT _result)
  164. set(_result "Failed to recognize symbols")
  165. endif()
  166. message(STATUS "Detecting Fortran/C Interface - ${_result}")