[CMake] CMAKE_*_IMPLICIT_INCLUDE_DIRECTORIES with MinGW

Olivier Croquette ocroquette at free.fr
Sat Nov 3 16:41:03 EDT 2018


Hi, 


I got recently build errors when introducing external dependencies in my project, the reason is that those components re-add standard SYSTEM include search paths, which changes the search order and causes #include_next to fail. The typical error message is: 
C:\...\lib\gcc\x86_64-w64-mingw32\7.2.0\include\c++\cstdlib:75: error: stdlib.h: No such file or directory 

at #include_next 





The following bug report against GCC describes the same issue independently of CMake, and apparently no improvement is to be expected from the compiler itself: 

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129 


So I rolled up my sleeves and implemented the following solution in CMake. It calls the preprocessor to get the standard include search paths and adds them to CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES and CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES. 
When a project or an external component tries to add them, CMake ignores this, and the search order stays unharmed. 

if("${CMAKE_MINGW_IMPLICIT_INCLUDE_DIRECTORIES}" STREQUAL "") 
# Run the preprocessor in verbose mode on an empty input 
execute_process( 
COMMAND 
"${CMAKE_CXX_COMPILER}" 
"-E" 
"-Wp,-v" 
"-" 
INPUT_FILE "NUL" # Special Windows file, equivalent to /dev/null 
OUTPUT_VARIABLE _mingw_cpp_out # Capture stdout 
ERROR_VARIABLE _mingw_cpp_error # Capture stderr 
) 

# Create list of lines from stderr output: 
string(REGEX REPLACE ";" "\\\\;" _mingw_cpp_error "${_mingw_cpp_error}") 
string(REGEX REPLACE "\n" ";" _mingw_cpp_error "${_mingw_cpp_error}") 

# Look for this text block and gather the paths: 
# #include search starts here: 
# C:/..../bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/include 
# C:/..../bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/include-fixed 
# C:/..../bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/include 
# End of search list. 
set(_mingw_cpp_list) 
foreach(_mingw_cpp_line ${_mingw_cpp_error}) 
if("${_mingw_cpp_line}" MATCHES "#include search starts here:") 
# Block starts 
set(_mingw_cpp_state "ON") 
elseif("${_mingw_cpp_line}" MATCHES "End of search list.") 
# Block ends 
set(_mingw_cpp_state "OFF") 
elseif("${_mingw_cpp_state}") 
# Within block 
# Clean up and beautify the path 
string(STRIP "${_mingw_cpp_line}" _mingw_cpp_line) 
get_filename_component(_mingw_cpp_line ${_mingw_cpp_line} REALPATH) 
list(APPEND _mingw_cpp_list ${_mingw_cpp_line}) 
endif() 
endforeach() 

# Set the list in the cache, so that we don't have to run the external process again 
set(CMAKE_MINGW_IMPLICIT_INCLUDE_DIRECTORIES ${_mingw_cpp_list} CACHE INTERNAL "List of MinGW system include paths") 
endif() 

list(APPEND CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_MINGW_IMPLICIT_INCLUDE_DIRECTORIES}) 
list(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_MINGW_IMPLICIT_INCLUDE_DIRECTORIES}) 







My question is: shouldn't this be done within the standard CMake distribution, when using any GCC based compiler? 





Olivier 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://cmake.org/pipermail/cmake/attachments/20181103/f8796cc8/attachment.html>


More information about the CMake mailing list