CMAKE_*_IMPLICIT_INCLUDE_DIRECTORIES with MinGW

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

CMAKE_*_IMPLICIT_INCLUDE_DIRECTORIES with MinGW

Olivier Croquette
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


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: CMAKE_*_IMPLICIT_INCLUDE_DIRECTORIES with MinGW

Olivier Croquette

Hi everyone,

any feedback on this?
As a summary, it's about adding the default include paths of GCC to the variables "CMAKE_*_IMPLICIT_INCLUDE_DIRECTORIES" to avoid CMake modules or scripts to mess up with them, more specifically with their order.

Cheers,
Olivier


On 2018-11-3 21:41, Olivier Croquette wrote:
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



--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: CMAKE_*_IMPLICIT_INCLUDE_DIRECTORIES with MinGW

Alan W. Irwin-2
On 2018-11-08 07:36+0100 Olivier Croquette wrote:

> Hi everyone,
>
> any feedback on this?
> As a summary, it's about adding the default include paths of GCC to the
> variables "CMAKE_*_IMPLICIT_INCLUDE_DIRECTORIES" to avoid CMake modules or
> scripts to mess up with them, more specifically with their order.

Hi Olivier:

I am afraid I cannot help you directly with your specific question
because I have no access to the Microsoft version of Windows, and it
has been a while since I worked with the Wine version of Windows.
However, for the sake of those who might be able to help you, I
suggest you clarify exactly what you mean by "MinGW". For example,
some possibilities are

1. MinGW, the traditional gcc variant for Windows.  This platform uses
    the CMake generator "MinGW Makefiles" and the MinGW version of GNU
    make.

2. MinGW-w64, a successor (with different developers, see
    <https://sourceforge.net/p/mingw-w64/wiki2>) to MinGW.  This
    platform uses the CMake generator "MinGW Makefiles" and the
    MinGW-w64 version of GNU make (see
    <https://sourceforge.net/p/mingw-w64/wiki2/Make/>)

3. MinGW/MSYS which combines the traditional gcc variant for Windows
    and a traditional Unix-like variant for Windows where MSYS is
    developed by the same group of developers as MinGW.  This platform
    uses the CMake generator "MSYS Makefiles" and the MSYS version of
    GNU make.

4. MinGW-w64/MSYS2 a successor to MinGW/MSYS where the MSYS2
    developers are a different group (See
    <https://github.com/msys2/msys2/wiki>) than the MinGW-w64
    developers and the MSYS developers. This platform uses the CMake
    generator "MSYS Makefiles" and the MSYS2 version of GNU make.

5. A slight variant of 4. which uses the "Unix Makefiles" generator.

The reasons these platform distinctions are important for your
question is the issue you have found might not be an issue for
some/most of them.  For example, years ago I did do comprehensive
(including static linking) tests of PLplot on platform 3 for the Wine
version of Windows, and I do not recall encountering the issue you
have described.  And my friend and PLplot colleague Arjen Markus who
comprehensively tests PLplot on platform 5 on a regular basis has also
never run into this issue according to the comprehensive test reports
he has sent to me over the years including one such report just last
week.

Of course, PLplot comprehensive tests might not expose the issue you
have discovered so I suggest you provide a self-contained minimal
CMake-based project (minimal C source code + CMake build system to
build it) which demonstrates the issue you have found on at least one
of the above platforms.  Once you supply that, others here can
conveniently use that test project to verify (or not) the issue on any
of the above 4 platforms.

Good luck with your further investigations into this issue!

Alan
__________________________
Alan W. Irwin

Programming affiliations with the FreeEOS equation-of-state
implementation for stellar interiors (freeeos.sf.net); the Time
Ephemerides project (timeephem.sf.net); PLplot scientific plotting
software package (plplot.sf.net); the libLASi project
(unifont.org/lasi); the Loads of Linux Links project (loll.sf.net);
and the Linux Brochure Project (lbproject.sf.net).
__________________________

Linux-powered Science
__________________________
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake