248 lines
9.1 KiB
CMake
248 lines
9.1 KiB
CMake
|
# 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 polution 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()
|
||
|
|
||
|
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 polution 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()
|