summaryrefslogtreecommitdiff
path: root/Modules/CMakeParseImplicitIncludeInfo.cmake
diff options
context:
space:
mode:
authorChuck Cranor <chuck@ece.cmu.edu>2018-12-07 07:48:17 -0700
committerBrad King <brad.king@kitware.com>2019-01-21 11:14:08 -0500
commit5990ecb74133e1a9c885fc0ea62896b501d37fef (patch)
tree9f74108839347d376a93224632fff228ed908021 /Modules/CMakeParseImplicitIncludeInfo.cmake
parentd751d2d2ed277c1bfb2882fd90b377983ab4700f (diff)
downloadcmake-5990ecb74133e1a9c885fc0ea62896b501d37fef.tar.gz
Compute implicit include directories from compiler output
- CMakeParseImplicitIncludeInfo.cmake: new parser that extracts the compiler's include path from verbose output. If the parser cannot parse the output, we fall back to the old behavior. On osx we skip over framework directories (handled elsewhere). - CMakeDetermineCompilerABI.cmake: - use verbose flag in try_compile for ${src} - use new cmake_parse_implicit_include_info() to attempt extract implicit include directory path and if successful set CMAKE_${LANG}_IMPLICIT_INCLUDE_DIRECTORIES - CMakeCCompiler.cmake.in and CMakeCXXCompiler.cmake.in - preserve CMAKE_${LANG}_IMPLICIT_INCLUDE_DIRECTORIES value between runs in the same way CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES is preserved - Tests/RunCMake/ParseImplicitIncludeInfo: tests for parse based on the older Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in. The test runs a set of verbose compiler outputs collected from various machines through the parser and checks the results. New compiler files can be added by dropping input/output files in the ParseImplicitIncludeInfo/data subdirectory and then adding the new set of files to the ${targets} list in ParseImplicitIncludeInfo.cmake. There is a helper CMakeLists.txt in ParseImplicitIncludeInfo/data that can help with the generation of test input files. NOTE: the standard cmake pre-commit hook rejects verbose compiler output with trailing spaces... you have to manually edit them out. This shouldn't impact the test. Note that both the parser and the test code can use CMAKE_${LANG}_COMPILER_* variables such as ${CMAKE_CXX_COMPILER_ID} to decide how to parse verbose compiler output. For the test code, this requires us to save the variables values in the test input files. Fixes: #16291
Diffstat (limited to 'Modules/CMakeParseImplicitIncludeInfo.cmake')
-rw-r--r--Modules/CMakeParseImplicitIncludeInfo.cmake95
1 files changed, 95 insertions, 0 deletions
diff --git a/Modules/CMakeParseImplicitIncludeInfo.cmake b/Modules/CMakeParseImplicitIncludeInfo.cmake
new file mode 100644
index 0000000000..9901fea48a
--- /dev/null
+++ b/Modules/CMakeParseImplicitIncludeInfo.cmake
@@ -0,0 +1,95 @@
+# 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 "")
+
+ # ccfe: cray compiler front end (PrgEnv-cray)
+ if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "Cray" AND
+ "${line}" MATCHES "-isystem")
+ 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()
+
+ if(log)
+ set(${log_var} "${log}" PARENT_SCOPE)
+ endif()
+ if(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)
+ string(APPEND log " found start of implicit 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()
+ else()
+ string(STRIP "${line}" path) # remove leading/trailing spaces
+ if ("${path}" MATCHES " \\(framework directory\\)$")
+ continue() # frameworks are handled elsewhere, ignore them here
+ endif()
+ string(REPLACE "\\" "/" path "${path}")
+ list(APPEND implicit_dirs_tmp "${path}")
+ string(APPEND log " add: [${path}]\n")
+ endif()
+ endif()
+ endforeach()
+
+ # Log results.
+ if(state STREQUAL done)
+ string(APPEND log " implicit include dirs: [${implicit_dirs_tmp}]\n")
+ else()
+ string(APPEND log " warn: unable to parse implicit include dirs!\n")
+ endif()
+
+ # Return results.
+ set(${dir_var} "${implicit_dirs_tmp}" PARENT_SCOPE)
+ set(${log_var} "${log}" PARENT_SCOPE)
+ set(${state_var} "${state}" PARENT_SCOPE)
+
+endfunction()