u3d-community / U3D

Open-source, cross-platform 2D and 3D game engine built in C++
https://u3d.io
MIT License
191 stars 30 forks source link

win-gcc Builds Failing #34

Open SirNate0 opened 1 year ago

SirNate0 commented 1 year ago

https://github.com/u3d-community/U3D/actions/runs/3949612987

CMake Error at cmake/Modules/FindDirectX.cmake:86 (message):
  Could not find MinGW system root.  Use MINGW_SYSROOT environment variable
  or build option to specify the location of system root.
Call Stack (most recent call first):
  cmake/Modules/UrhoCommon.cmake:504 (find_package)
  CMakeLists.txt:33 (include)

-- Configuring incomplete, errors occurred!
See also "D:/a/U3D/U3D/build/ci/CMakeFiles/CMakeOutput.log".
script/cmake_mingw.bat "build/ci"  -D URHO3D_EXTRAS=1 -D URHO3D_DOCS=0 -D URHO3D_DATABASE_SQLITE=1 
    -D URHO3D_TESTING=1 -D URHO3D_OPENGL=1 -D URHO3D_LIB_TYPE=SHARED -D URHO3D_DEPLOYMENT_TARGET=generic 
    -D CMAKE_INSTALL_PREFIX=C:/Users/runneradmin/.urho3d/install/win-mingw
Error: Process completed with exit code 1.
iSLC commented 1 year ago

I remember bumping into this a while back. In my case I updated the if (MINGW) branch from FindDirectX.cmake from this:

    if (MINGW)
        # Intentionally searching for d3dcompiler(_XX) libraries in this particular order, avoiding unversioned d3dcompiler library so we know exactly which DLL to use
        set (D3DCOMPILER_NAMES d3dcompiler_47 d3dcompiler_46 d3dcompiler_43 d3dcompiler_42)
        if (NOT MINGW_SYSROOT)
            if (DEFINED ENV{MINGW_SYSROOT})
                file (TO_CMAKE_PATH $ENV{MINGW_SYSROOT} MINGW_SYSROOT)
            else ()
                execute_process (COMMAND ${CMAKE_COMMAND} -E echo "#include <_mingw.h>" COMMAND ${CMAKE_C_COMPILER} -E -M - OUTPUT_FILE ${CMAKE_BINARY_DIR}/find_mingw_sysroot_output ERROR_QUIET)
                file (STRINGS ${CMAKE_BINARY_DIR}/find_mingw_sysroot_output MINGW_SYSROOT REGEX _mingw\\.h)
                string (REGEX REPLACE "^[^ ]* *(.*)/include.*$" \\1 MINGW_SYSROOT "${MINGW_SYSROOT}")  # Stringify for string replacement
                string (REPLACE "\\ " " " MINGW_SYSROOT "${MINGW_SYSROOT}")
                execute_process (COMMAND ${CMAKE_COMMAND} -E remove find_mingw_sysroot_output)
            endif ()
            if (NOT EXISTS ${MINGW_SYSROOT})
                message (FATAL_ERROR "Could not find MinGW system root. "
                    "Use MINGW_SYSROOT environment variable or build option to specify the location of system root.")
            endif ()
            set (MINGW_SYSROOT ${MINGW_SYSROOT} CACHE PATH "Path to MinGW system root (MinGW only); should only be used when the system root could not be auto-detected" FORCE)
        endif ()
        # MinGW Cross-compiling uses CMAKE_FIND_ROOT_PATH while MinGW on Windows host uses CMAKE_PREFIX_PATH
        if (CMAKE_HOST_WIN32)
            set (CMAKE_PREFIX_PATH ${MINGW_SYSROOT})
        endif ()
        # MinGW does not usually need search paths as DirectX headers and libraries (when installed) are in its default search path
        # However, we do not explicitly unset the DIRECTX_INC_SEARCH_PATHS and DIRECTX_LIB_SEARCH_PATHS variables here, so module user could set these two variables externally when for some reasons the DirectX headers and libraries are not installed in MinGW default search path

To this:

    if (MINGW)
        # Intentionally searching for d3dcompiler(_XX) libraries in this particular order, avoiding unversioned d3dcompiler library so we know exactly which DLL to use
        set (D3DCOMPILER_NAMES d3dcompiler_47 d3dcompiler_46 d3dcompiler_43 d3dcompiler_42)

        # In certain cases (like with chocolatey) we may have multiple prefix paths to look for libraries
        set (MINGW_SYSROOTS NULL)

        if (NOT MINGW_SYSROOT)
            if (DEFINED ENV{MINGW_SYSROOT})
                file (TO_CMAKE_PATH $ENV{MINGW_SYSROOT} MINGW_SYSROOT)
            else ()
                execute_process (COMMAND ${CMAKE_COMMAND} -E echo "#include <_mingw.h>" COMMAND ${CMAKE_C_COMPILER} -E -M - OUTPUT_FILE ${CMAKE_BINARY_DIR}/find_mingw_sysroot_output ERROR_QUIET)
                file (STRINGS ${CMAKE_BINARY_DIR}/find_mingw_sysroot_output MINGW_SYSROOT REGEX _mingw\\.h)
                string (REGEX REPLACE "^[^ ]* *(.*)/include.*$" \\1 MINGW_SYSROOT "${MINGW_SYSROOT}")  # Stringify for string replacement
                string (REPLACE "\\ " " " MINGW_SYSROOT "${MINGW_SYSROOT}")
                execute_process (COMMAND ${CMAKE_COMMAND} -E remove find_mingw_sysroot_output)
            endif ()
            # Try an alternate method
            if (NOT EXISTS ${MINGW_SYSROOT} AND WIN32)
                execute_process (COMMAND where.exe "mingw32-make.exe" OUTPUT_VARIABLE MINGW_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
                get_filename_component (MINGW_SYSROOT ${MINGW_SYSROOT} DIRECTORY REALPATH) # Remove `/mingw32-make.exe` from the path
                get_filename_component (MINGW_SYSROOT ${MINGW_SYSROOT} DIRECTORY REALPATH) # Remove `/bin` from the path
                # Check if this is the chocolatey variant of mingw64 with different directory structure
                # In which case we have to go a little deeper to find the libraries we need
                if (IS_DIRECTORY "${MINGW_SYSROOT}/lib/mingw/tools/install/mingw64")
                    set (MINGW_SYSROOTS "${MINGW_SYSROOT}/lib/mingw/tools/install/mingw64")
                    # D3D components are actually located in this folder
                    # Folders above this one also contain various libraries. But not the ones we're looking for
                    # TODO: see if this can have a different name depending on the architecture
                    if (IS_DIRECTORY "${MINGW_SYSROOTS}/x86_64-w64-mingw32")
                        set (MINGW_SYSROOTS "${MINGW_SYSROOTS}/x86_64-w64-mingw32;${MINGW_SYSROOTS}")
                    endif ()
                endif ()
            endif()
            if (NOT EXISTS ${MINGW_SYSROOT})
                message (FATAL_ERROR "Could not find MinGW system root. "
                    "Use MINGW_SYSROOT environment variable or build option to specify the location of system root.")
            endif ()
            set (MINGW_SYSROOT ${MINGW_SYSROOT} CACHE PATH "Path to MinGW system root (MinGW only); should only be used when the system root could not be auto-detected" FORCE)
        endif ()
        # MinGW Cross-compiling uses CMAKE_FIND_ROOT_PATH while MinGW on Windows host uses CMAKE_PREFIX_PATH
        if (CMAKE_HOST_WIN32)
            set (CMAKE_PREFIX_PATH ${MINGW_SYSROOT})
        endif ()
        # Extra prefixes for special cases and special directory structures
        if(MINGW_SYSROOTS)
            set (CMAKE_PREFIX_PATH "${MINGW_SYSROOTS};${MINGW_SYSROOT}")
        endif()
        # MinGW does not usually need search paths as DirectX headers and libraries (when installed) are in its default search path
        # However, we do not explicitly unset the DIRECTX_INC_SEARCH_PATHS and DIRECTX_LIB_SEARCH_PATHS variables here, so module user could set these two variables externally when for some reasons the DirectX headers and libraries are not installed in MinGW default search path

The extra fallback steps for chocolatey are not that necessary. I just remember having issues with it because by default, github windows image uses the chocolatey variant of mingw which has a different directory structure.

Later on I switched to the MSYS2 variant of mingw (https://github.com/marketplace/actions/setup-msys2 ) because it made things simpler identical to my local setup.

Basically, instead of looking for the _mingw.h header I'm looking for the mingw32-make.exe executable to find the bin folder and from then on I just pop the folders until root.

Not extensively tested on multiple architectures and platforms or cross-builds.