Detect.cmake 5.9 KB

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