CMakeParseImplicitIncludeInfo.cmake 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file Copyright.txt or https://cmake.org/licensing for details.
  3. # This is used internally by CMake and should not be included by user code.
  4. # helper function that parses implicit include dirs from a single line
  5. # for compilers that report them that way. on success we return the
  6. # list of dirs in id_var and set state_var to the 'done' state.
  7. function(cmake_parse_implicit_include_line line lang id_var log_var state_var)
  8. # clear variables we append to (avoids possible polution from parent scopes)
  9. unset(rv)
  10. set(log "")
  11. # Cray compiler (from cray wrapper, via PrgEnv-cray)
  12. if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "Cray" AND
  13. "${line}" MATCHES "^/" AND "${line}" MATCHES "/ccfe |/ftnfe " AND
  14. "${line}" MATCHES " -isystem| -I")
  15. string(REGEX MATCHALL " (-I ?|-isystem )([^ ]*)" incs "${line}")
  16. foreach(inc IN LISTS incs)
  17. string(REGEX REPLACE " (-I ?|-isystem )([^ ]*)" "\\2" idir "${inc}")
  18. list(APPEND rv "${idir}")
  19. endforeach()
  20. if(rv)
  21. string(APPEND log " got implicit includes via cray ccfe parser!\n")
  22. else()
  23. string(APPEND log " warning: cray ccfe parse failed!\n")
  24. endif()
  25. endif()
  26. # SunPro compiler
  27. if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "SunPro" AND
  28. "${line}" MATCHES "-D__SUNPRO_C")
  29. string(REGEX MATCHALL " (-I ?)([^ ]*)" incs "${line}")
  30. foreach(inc IN LISTS incs)
  31. string(REGEX REPLACE " (-I ?)([^ ]*)" "\\2" idir "${inc}")
  32. if(NOT "${idir}" STREQUAL "-xbuiltin")
  33. list(APPEND rv "${idir}")
  34. endif()
  35. endforeach()
  36. if(rv)
  37. # /usr/include appears to be hardwired in
  38. list(APPEND rv "/usr/include")
  39. string(APPEND log " got implicit includes via sunpro parser!\n")
  40. else()
  41. string(APPEND log " warning: sunpro parse failed!\n")
  42. endif()
  43. endif()
  44. # XL compiler
  45. if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "XL" AND "${line}" MATCHES "^/"
  46. AND ( ("${lang}" STREQUAL "Fortran" AND
  47. "${line}" MATCHES "/xl[fF]entry " AND
  48. "${line}" MATCHES "OSVAR\\([^ ]+\\)")
  49. OR
  50. ( ("${lang}" STREQUAL "C" OR "${lang}" STREQUAL "CXX") AND
  51. "${line}" MATCHES "/xl[cC]entry " AND
  52. "${line}" MATCHES " -qosvar=")
  53. ) )
  54. # -qnostdinc cancels other stdinc flags, even if present
  55. string(FIND "${line}" " -qnostdinc" nostd)
  56. if(NOT ${nostd} EQUAL -1)
  57. set(rv "") # defined but empty
  58. string(APPEND log " got implicit includes via XL parser (nostdinc)\n")
  59. else()
  60. if("${lang}" STREQUAL "CXX")
  61. string(REGEX MATCHALL " -qcpp_stdinc=([^ ]*)" std "${line}")
  62. string(REGEX MATCHALL " -qgcc_cpp_stdinc=([^ ]*)" gcc_std "${line}")
  63. else()
  64. string(REGEX MATCHALL " -qc_stdinc=([^ ]*)" std "${line}")
  65. string(REGEX MATCHALL " -qgcc_c_stdinc=([^ ]*)" gcc_std "${line}")
  66. endif()
  67. set(xlstd ${std} ${gcc_std})
  68. foreach(inc IN LISTS xlstd)
  69. string(REGEX REPLACE " -q(cpp|gcc_cpp|c|gcc_c)_stdinc=([^ ]*)" "\\2"
  70. ipath "${inc}")
  71. string(REPLACE ":" ";" ipath "${ipath}")
  72. list(APPEND rv ${ipath})
  73. endforeach()
  74. endif()
  75. # user can add -I flags via CMAKE_{C,CXX}_FLAGS, look for that too
  76. string(REGEX MATCHALL " (-I ?)([^ ]*)" incs "${line}")
  77. unset(urv)
  78. foreach(inc IN LISTS incs)
  79. string(REGEX REPLACE " (-I ?)([^ ]*)" "\\2" idir "${inc}")
  80. list(APPEND urv "${idir}")
  81. endforeach()
  82. if(urv)
  83. if ("${rv}" STREQUAL "")
  84. set(rv ${urv})
  85. else()
  86. list(APPEND rv ${urv})
  87. endif()
  88. endif()
  89. if(DEFINED rv)
  90. string(APPEND log " got implicit includes via XL parser!\n")
  91. else()
  92. string(APPEND log " warning: XL parse failed!\n")
  93. endif()
  94. endif()
  95. if(log)
  96. set(${log_var} "${log}" PARENT_SCOPE)
  97. else()
  98. unset(${log_var} PARENT_SCOPE)
  99. endif()
  100. if(DEFINED rv)
  101. set(${id_var} "${rv}" PARENT_SCOPE)
  102. set(${state_var} "done" PARENT_SCOPE)
  103. endif()
  104. endfunction()
  105. # top-level function to parse implicit include directory information
  106. # from verbose compiler output. sets state_var in parent to 'done' on success.
  107. function(cmake_parse_implicit_include_info text lang dir_var log_var state_var)
  108. set(state start) # values: start, loading, done
  109. # clear variables we append to (avoids possible polution from parent scopes)
  110. set(implicit_dirs_tmp)
  111. set(log "")
  112. # go through each line of output...
  113. string(REGEX REPLACE "\r?\n" ";" output_lines "${text}")
  114. foreach(line IN LISTS output_lines)
  115. if(state STREQUAL start)
  116. string(FIND "${line}" "#include \"...\" search starts here:" rv)
  117. if(rv GREATER -1)
  118. set(state loading)
  119. set(preload 1) # looking for include <...> now
  120. string(APPEND log " found start of include info\n")
  121. else()
  122. cmake_parse_implicit_include_line("${line}" "${lang}" implicit_dirs_tmp
  123. linelog state)
  124. if(linelog)
  125. string(APPEND log ${linelog})
  126. endif()
  127. if(state STREQUAL done)
  128. break()
  129. endif()
  130. endif()
  131. elseif(state STREQUAL loading)
  132. string(FIND "${line}" "End of search list." rv)
  133. if(rv GREATER -1)
  134. set(state done)
  135. string(APPEND log " end of search list found\n")
  136. break()
  137. endif()
  138. if(preload)
  139. string(FIND "${line}" "#include <...> search starts here:" rv)
  140. if(rv GREATER -1)
  141. set(preload 0)
  142. string(APPEND log " found start of implicit include info\n")
  143. endif()
  144. continue()
  145. endif()
  146. if("${line}" MATCHES "^ ")
  147. string(SUBSTRING "${line}" 1 -1 line) # remove leading space
  148. endif()
  149. if ("${line}" MATCHES " \\(framework directory\\)$")
  150. continue() # frameworks are handled elsewhere, ignore them here
  151. endif()
  152. string(REPLACE "\\" "/" path "${line}")
  153. list(APPEND implicit_dirs_tmp "${path}")
  154. string(APPEND log " add: [${path}]\n")
  155. endif()
  156. endforeach()
  157. # Log results.
  158. if(state STREQUAL done)
  159. string(APPEND log " implicit include dirs: [${implicit_dirs_tmp}]\n")
  160. else()
  161. string(APPEND log " warn: unable to parse implicit include dirs!\n")
  162. endif()
  163. # Return results.
  164. set(${dir_var} "${implicit_dirs_tmp}" PARENT_SCOPE)
  165. set(${log_var} "${log}" PARENT_SCOPE)
  166. set(${state_var} "${state}" PARENT_SCOPE)
  167. endfunction()