| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| # file Copyright.txt or https://cmake.org/licensing for details. | |
| # This is used internally by CMake and should not be included by user code. | |
| # helper function that parses implicit include dirs from a single line | |
| # for compilers that report them that way. on success we return the | |
| # list of dirs in id_var and set state_var to the 'done' state. | |
| function(cmake_parse_implicit_include_line line lang id_var log_var state_var) | |
| # clear variables we append to (avoids possible pollution from parent scopes) | |
| unset(rv) | |
| set(log "") | |
| # Cray compiler (from cray wrapper, via PrgEnv-cray) | |
| if(CMAKE_${lang}_COMPILER_ID STREQUAL "Cray" AND | |
| line MATCHES "^/" AND line MATCHES "/ccfe |/ftnfe " AND | |
| line MATCHES " -isystem| -I") | |
| string(REGEX MATCHALL " (-I ?|-isystem )(\"[^\"]+\"|[^ \"]+)" incs "${line}") | |
| foreach(inc IN LISTS incs) | |
| string(REGEX REPLACE " (-I ?|-isystem )(\"[^\"]+\"|[^ \"]+)" "\\2" idir "${inc}") | |
| list(APPEND rv "${idir}") | |
| endforeach() | |
| if(rv) | |
| string(APPEND log " got implicit includes via cray ccfe parser!\n") | |
| else() | |
| string(APPEND log " warning: cray ccfe parse failed!\n") | |
| endif() | |
| endif() | |
| # PGI compiler | |
| if(CMAKE_${lang}_COMPILER_ID STREQUAL "PGI") | |
| # pgc++ verbose output differs | |
| if((lang STREQUAL "C" OR lang STREQUAL "Fortran") AND | |
| line MATCHES "^/" AND | |
| line MATCHES "/pgc |/pgf901 |/pgftnc " AND | |
| line MATCHES " -cmdline ") | |
| # cmdline has unparsed cmdline, remove it | |
| string(REGEX REPLACE "-cmdline .*" "" line "${line}") | |
| if("${line}" MATCHES " -nostdinc ") | |
| set(rv "") # defined, but empty | |
| else() | |
| string(REGEX MATCHALL " -stdinc ([^ ]*)" incs "${line}") | |
| foreach(inc IN LISTS incs) | |
| string(REGEX REPLACE " -stdinc ([^ ]*)" "\\1" idir "${inc}") | |
| string(REPLACE ":" ";" idir "${idir}") | |
| list(APPEND rv ${idir}) | |
| endforeach() | |
| endif() | |
| if(DEFINED rv) | |
| string(APPEND log " got implicit includes via PGI C/F parser!\n") | |
| else() | |
| string(APPEND log " warning: PGI C/F parse failed!\n") | |
| endif() | |
| elseif(lang STREQUAL "CXX" AND line MATCHES "^/" AND | |
| line MATCHES "/pggpp1 " AND line MATCHES " -I") | |
| # oddly, -Mnostdinc does not get rid of system -I's, at least in | |
| # PGI 18.10.1 ... | |
| string(REGEX MATCHALL " (-I ?)([^ ]*)" incs "${line}") | |
| foreach(inc IN LISTS incs) | |
| string(REGEX REPLACE " (-I ?)([^ ]*)" "\\2" idir "${inc}") | |
| if(NOT idir STREQUAL "-") # filter out "-I-" | |
| list(APPEND rv "${idir}") | |
| endif() | |
| endforeach() | |
| if(DEFINED rv) | |
| string(APPEND log " got implicit includes via PGI CXX parser!\n") | |
| else() | |
| string(APPEND log " warning: PGI CXX parse failed!\n") | |
| endif() | |
| endif() | |
| endif() | |
| # SunPro compiler | |
| if(CMAKE_${lang}_COMPILER_ID STREQUAL "SunPro" AND | |
| (line MATCHES "-D__SUNPRO_C" OR line MATCHES "-D__SUNPRO_F")) | |
| string(REGEX MATCHALL " (-I ?)([^ ]*)" incs "${line}") | |
| foreach(inc IN LISTS incs) | |
| string(REGEX REPLACE " (-I ?)([^ ]*)" "\\2" idir "${inc}") | |
| if(NOT "${idir}" STREQUAL "-xbuiltin") | |
| list(APPEND rv "${idir}") | |
| endif() | |
| endforeach() | |
| if(rv) | |
| if (lang STREQUAL "C" OR lang STREQUAL "CXX") | |
| # /usr/include appears to be hardwired in | |
| list(APPEND rv "/usr/include") | |
| endif() | |
| string(APPEND log " got implicit includes via sunpro parser!\n") | |
| else() | |
| string(APPEND log " warning: sunpro parse failed!\n") | |
| endif() | |
| endif() | |
| # XL compiler | |
| if((CMAKE_${lang}_COMPILER_ID STREQUAL "XL" | |
| OR CMAKE_${lang}_COMPILER_ID STREQUAL "XLClang") | |
| AND line MATCHES "^/" | |
| AND ( (lang STREQUAL "Fortran" AND | |
| line MATCHES "/xl[fF]entry " AND | |
| line MATCHES "OSVAR\\([^ ]+\\)") | |
| OR | |
| ( (lang STREQUAL "C" OR lang STREQUAL "CXX") AND | |
| line MATCHES "/xl[cC]2?entry " AND | |
| line MATCHES " -qosvar=") | |
| ) ) | |
| # -qnostdinc cancels other stdinc flags, even if present | |
| string(FIND "${line}" " -qnostdinc" nostd) | |
| if(NOT nostd EQUAL -1) | |
| set(rv "") # defined but empty | |
| string(APPEND log " got implicit includes via XL parser (nostdinc)\n") | |
| else() | |
| if(lang STREQUAL "CXX") | |
| string(REGEX MATCHALL " -qcpp_stdinc=([^ ]*)" std "${line}") | |
| string(REGEX MATCHALL " -qgcc_cpp_stdinc=([^ ]*)" gcc_std "${line}") | |
| else() | |
| string(REGEX MATCHALL " -qc_stdinc=([^ ]*)" std "${line}") | |
| string(REGEX MATCHALL " -qgcc_c_stdinc=([^ ]*)" gcc_std "${line}") | |
| endif() | |
| set(xlstd ${std} ${gcc_std}) | |
| foreach(inc IN LISTS xlstd) | |
| string(REGEX REPLACE " -q(cpp|gcc_cpp|c|gcc_c)_stdinc=([^ ]*)" "\\2" | |
| ipath "${inc}") | |
| string(REPLACE ":" ";" ipath "${ipath}") | |
| list(APPEND rv ${ipath}) | |
| endforeach() | |
| endif() | |
| # user can add -I flags via CMAKE_{C,CXX}_FLAGS, look for that too | |
| string(REGEX MATCHALL " (-I ?)([^ ]*)" incs "${line}") | |
| unset(urv) | |
| foreach(inc IN LISTS incs) | |
| string(REGEX REPLACE " (-I ?)([^ ]*)" "\\2" idir "${inc}") | |
| list(APPEND urv "${idir}") | |
| endforeach() | |
| if(urv) | |
| if ("${rv}" STREQUAL "") | |
| set(rv ${urv}) | |
| else() | |
| list(APPEND rv ${urv}) | |
| endif() | |
| endif() | |
| if(DEFINED rv) | |
| string(APPEND log " got implicit includes via XL parser!\n") | |
| else() | |
| string(APPEND log " warning: XL parse failed!\n") | |
| endif() | |
| endif() | |
| # Fujitsu compiler | |
| if(CMAKE_${lang}_COMPILER_ID STREQUAL "Fujitsu" AND | |
| line MATCHES "/ccpcom") | |
| string(REGEX MATCHALL " (-I *|--sys_include=|--preinclude +)(\"[^\"]+\"|[^ \"]+)" incs "${line}") | |
| foreach(inc IN LISTS incs) | |
| string(REGEX REPLACE " (-I *|--sys_include=|--preinclude +)(\"[^\"]+\"|[^ \"]+)" "\\2" idir "${inc}") | |
| list(APPEND rv "${idir}") | |
| endforeach() | |
| if(rv) | |
| string(APPEND log " got implicit includes via fujitsu ccpcom parser!\n") | |
| else() | |
| string(APPEND log " warning: fujitsu ccpcom parse failed!\n") | |
| endif() | |
| endif() | |
| if(log) | |
| set(${log_var} "${log}" PARENT_SCOPE) | |
| else() | |
| unset(${log_var} PARENT_SCOPE) | |
| endif() | |
| if(DEFINED rv) | |
| set(${id_var} "${rv}" PARENT_SCOPE) | |
| set(${state_var} "done" PARENT_SCOPE) | |
| endif() | |
| endfunction() | |
| # top-level function to parse implicit include directory information | |
| # from verbose compiler output. sets state_var in parent to 'done' on success. | |
| function(cmake_parse_implicit_include_info text lang dir_var log_var state_var) | |
| set(state start) # values: start, loading, done | |
| # clear variables we append to (avoids possible pollution from parent scopes) | |
| set(implicit_dirs_tmp) | |
| set(log "") | |
| # go through each line of output... | |
| string(REGEX REPLACE "\r*\n" ";" output_lines "${text}") | |
| foreach(line IN LISTS output_lines) | |
| if(state STREQUAL start) | |
| string(FIND "${line}" "#include \"...\" search starts here:" rv) | |
| if(rv GREATER -1) | |
| set(state loading) | |
| set(preload 1) # looking for include <...> now | |
| string(APPEND log " found start of include info\n") | |
| else() | |
| cmake_parse_implicit_include_line("${line}" "${lang}" implicit_dirs_tmp | |
| linelog state) | |
| if(linelog) | |
| string(APPEND log ${linelog}) | |
| endif() | |
| if(state STREQUAL done) | |
| break() | |
| endif() | |
| endif() | |
| elseif(state STREQUAL loading) | |
| string(FIND "${line}" "End of search list." rv) | |
| if(rv GREATER -1) | |
| set(state done) | |
| string(APPEND log " end of search list found\n") | |
| break() | |
| endif() | |
| if(preload) | |
| string(FIND "${line}" "#include <...> search starts here:" rv) | |
| if(rv GREATER -1) | |
| set(preload 0) | |
| string(APPEND log " found start of implicit include info\n") | |
| endif() | |
| continue() | |
| endif() | |
| if("${line}" MATCHES "^ ") | |
| string(SUBSTRING "${line}" 1 -1 line) # remove leading space | |
| endif() | |
| if ("${line}" MATCHES " \\(framework directory\\)$") | |
| continue() # frameworks are handled elsewhere, ignore them here | |
| endif() | |
| string(REPLACE "\\" "/" path "${line}") | |
| list(APPEND implicit_dirs_tmp "${path}") | |
| string(APPEND log " add: [${path}]\n") | |
| endif() | |
| endforeach() | |
| set(implicit_dirs "") | |
| foreach(d IN LISTS implicit_dirs_tmp) | |
| if(IS_ABSOLUTE "${d}") | |
| get_filename_component(dir "${d}" ABSOLUTE) | |
| list(APPEND implicit_dirs "${dir}") | |
| string(APPEND log " collapse include dir [${d}] ==> [${dir}]\n") | |
| elseif("${d}" MATCHES [[^\.\.[\/]\.\.[\/](.*)$]]) | |
| # This relative path is deep enough to get out of the CMakeFiles/CMakeTmp | |
| # directory where the ABI check is done. Assume that the compiler has | |
| # computed this path adaptively based on the current working directory | |
| # such that the effective result is absolute. | |
| get_filename_component(dir "${CMAKE_BINARY_DIR}/${CMAKE_MATCH_1}" ABSOLUTE) | |
| list(APPEND implicit_dirs "${dir}") | |
| string(APPEND log " collapse relative include dir [${d}] ==> [${dir}]\n") | |
| else() | |
| string(APPEND log " skipping relative include dir [${d}]\n") | |
| endif() | |
| endforeach() | |
| list(REMOVE_DUPLICATES implicit_dirs) | |
| # Log results. | |
| if(state STREQUAL done) | |
| string(APPEND log " implicit include dirs: [${implicit_dirs}]\n") | |
| else() | |
| string(APPEND log " warn: unable to parse implicit include dirs!\n") | |
| endif() | |
| # Return results. | |
| set(${dir_var} "${implicit_dirs}" PARENT_SCOPE) | |
| set(${log_var} "${log}" PARENT_SCOPE) | |
| set(${state_var} "${state}" PARENT_SCOPE) | |
| endfunction() |