Explorar el Código

Prevent *-PREFIX and *-SYSROOT changes after the initial configuration.
When in try_compile() mode, quickly obtain the previously cached values stored in the (inner scope) environment variables and bypass all the checks (which are already done when the toolchain file is being processed at the start of CMake run).

Yao Wei Tjong 姚伟忠 hace 9 años
padre
commit
06638436c0

+ 4 - 4
CMake/Modules/UrhoCommon.cmake

@@ -20,10 +20,10 @@
 # THE SOFTWARE.
 #
 
-# Save the original values of CC and CXX environment variables as they are not saved yet when no CMake toolchain file is being used
+# Save the initial values of CC and CXX environment variables
 if (NOT CMAKE_CROSSCOMPILING)
-    set (SAVED_CC $ENV{CC})
-    set (SAVED_CXX $ENV{CXX})
+    set (SAVED_CC $ENV{CC} CACHE INTERNAL "Initial value for CC")
+    set (SAVED_CXX $ENV{CXX} CACHE INTERNAL "Initial value for CXX")
 endif ()
 
 # Limit the supported build configurations
@@ -324,7 +324,7 @@ if (URHO3D_LUAJIT)
 endif ()
 
 # Union all the sysroot variables into one so it can be referred to generically later
-set (SYSROOT ${CMAKE_SYSROOT} ${MINGW_SYSROOT} ${IOS_SYSROOT} ${EMSCRIPTEN_SYSROOT} CACHE INTERNAL "Path to system root of the cross-compiling target")  # SYSROOT is empty for native build
+set (SYSROOT ${CMAKE_SYSROOT} ${MINGW_SYSROOT} ${IOS_SYSROOT} CACHE INTERNAL "Path to system root of the cross-compiling target")  # SYSROOT is empty for native build
 
 # Clang tools building
 if (URHO3D_CLANG_TOOLS OR URHO3D_BINDINGS)

+ 66 - 51
CMake/Toolchains/arm-linux.toolchain.cmake

@@ -20,12 +20,27 @@
 # THE SOFTWARE.
 #
 
-# Save the original values of CC and CXX environment variables before they get altered by CMake later
-if (DEFINED CMAKE_CROSSCOMPILING)
-    return ()
+# Workaround try_compile() limitation where it cannot yet see cache variables during initial configuration
+get_property (IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
+if (IN_TRY_COMPILE)
+    foreach (VAR $ENV{VARS})
+        set (${VAR} $ENV{${VAR}})
+    endforeach ()
 else ()
-    set (SAVED_CC $ENV{CC})
-    set (SAVED_CXX $ENV{CXX})
+    # Prevent critical variables from changing after the initial configuration
+    if (CMAKE_CROSSCOMPILING)
+        set (SAVED_ARM_SYSROOT ${ARM_SYSROOT} CACHE INTERNAL "Initial value for ARM_SYSROOT")
+        set (SAVED_ARM_PREFIX ${ARM_PREFIX} CACHE INTERNAL "Initial value for ARM_PREFIX")
+        # Save the initial values of CC and CXX environment variables
+        set (SAVED_CC $ENV{CC} CACHE INTERNAL "Initial value for CC")
+        set (SAVED_CXX $ENV{CXX} CACHE INTERNAL "Initial value for CXX")
+        return ()
+    elseif ((SAVED_ARM_SYSROOT AND NOT SAVED_ARM_SYSROOT STREQUAL ARM_SYSROOT) OR (SAVED_ARM_PREFIX AND NOT SAVED_ARM_PREFIX STREQUAL ARM_PREFIX))
+        set (ARM_SYSROOT ${SAVED_ARM_SYSROOT} CACHE PATH "Path to ARM system root (ARM on Linux cross-compiling build only)" FORCE)
+        set (ARM_PREFIX ${SAVED_ARM_PREFIX} CACHE STRING "Prefix path to ARM cross-compiler tools (ARM on Linux cross-compiling build only)" FORCE)
+        message (FATAL_ERROR "ARM_SYSROOT and ARM_PREFIX cannot be changed after the initial configuration/generation. "
+            "If you wish to change that then the build tree would have to be regenerated from scratch. Auto reverting to its initial value.")
+    endif ()
 endif ()
 
 # Reference toolchain variable to suppress "unused variable" warning
@@ -33,31 +48,48 @@ if (CMAKE_TOOLCHAIN_FILE)
     mark_as_advanced (CMAKE_TOOLCHAIN_FILE)
 endif ()
 
-# this one is important
+# This one is important
 set (CMAKE_SYSTEM_NAME Linux)
-# this one not so much
+# This one not so much
 set (CMAKE_SYSTEM_PROCESSOR arm)
 set (CMAKE_SYSTEM_VERSION 1)
 
-# specify the cross compiler
-if (NOT ARM_PREFIX AND DEFINED ENV{ARM_PREFIX})
-    file (TO_CMAKE_PATH $ENV{ARM_PREFIX} ARM_PREFIX)
+# System root
+if (NOT IN_TRY_COMPILE AND NOT SAVED_ARM_SYSROOT)
+    if (NOT ARM_SYSROOT AND DEFINED ENV{ARM_SYSROOT})
+        file (TO_CMAKE_PATH $ENV{ARM_SYSROOT} ARM_SYSROOT)
+    endif ()
+    set (ARM_SYSROOT ${ARM_SYSROOT} CACHE PATH "Path to ARM system root (ARM on Linux cross-compiling build only)")
+    if (NOT EXISTS ${ARM_SYSROOT})
+        message (FATAL_ERROR "Could not find ARM system root. "
+            "Use ARM_SYSROOT environment variable or build option to specify the location of system root.")
+    endif ()
 endif ()
-if (NOT EXISTS ${ARM_PREFIX}-gcc)
-    message (FATAL_ERROR "Could not find ARM cross compilation tool. "
-        "Use ARM_PREFIX environment variable or build option to specify the location of the toolchain.")
+set (CMAKE_SYSROOT ${ARM_SYSROOT})
+# Only search libraries and headers in sysroot
+set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+# Cross compiler tools
+if (NOT IN_TRY_COMPILE AND NOT SAVED_ARM_PREFIX)
+    if (NOT ARM_PREFIX AND DEFINED ENV{ARM_PREFIX})
+        file (TO_CMAKE_PATH $ENV{ARM_PREFIX} ARM_PREFIX)
+    endif ()
+    set (ARM_PREFIX ${ARM_PREFIX} CACHE STRING "Prefix path to ARM cross-compiler tools (ARM on Linux cross-compiling build only)")
+    if (NOT EXISTS ${ARM_PREFIX}-gcc)
+        message (FATAL_ERROR "Could not find ARM cross compilation tool. "
+            "Use ARM_PREFIX environment variable or build option to specify the location of the toolchain.")
+    endif ()
 endif ()
-set (COMPILER_PREFIX ${ARM_PREFIX})
-if (NOT CMAKE_C_COMPILER)
-    if (DEFINED ENV{CMAKE_C_COMPILER} AND DEFINED ENV{CMAKE_CXX_COMPILER})
-        set (CMAKE_C_COMPILER $ENV{CMAKE_C_COMPILER})
-        set (CMAKE_CXX_COMPILER $ENV{CMAKE_CXX_COMPILER})
-    elseif ("$ENV{USE_CCACHE}")
+if (NOT ARM_COMPILER_PREFIX)
+    set (ARM_COMPILER_PREFIX ${ARM_PREFIX})
+    if ("$ENV{USE_CCACHE}")
         get_filename_component (PATH ${ARM_PREFIX} PATH)
         get_filename_component (NAME ${ARM_PREFIX} NAME)
         execute_process (COMMAND whereis -b ccache COMMAND grep -o \\S*lib\\S* OUTPUT_VARIABLE CCACHE_SYMLINK ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
         if (CCACHE_SYMLINK AND EXISTS ${CCACHE_SYMLINK}/${NAME}-gcc AND EXISTS ${CCACHE_SYMLINK}/${NAME}-g++)
-            set (COMPILER_PREFIX ${CCACHE_SYMLINK}/${NAME})
+            set (ARM_COMPILER_PREFIX ${CCACHE_SYMLINK}/${NAME})
         else ()
             # Fallback to create the ccache symlink in the build tree itself
             execute_process (COMMAND which ccache RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE CCACHE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -65,7 +97,7 @@ if (NOT CMAKE_C_COMPILER)
                 foreach (TOOL gcc g++)
                     execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${NAME}-${TOOL})
                 endforeach ()
-                set (COMPILER_PREFIX ${CMAKE_BINARY_DIR}/${NAME})
+                set (ARM_COMPILER_PREFIX ${CMAKE_BINARY_DIR}/${NAME})
             else ()
                 message (WARNING "ccache may not have been installed on this host system. "
                     "This is required to enable ccache support for ARM compiler toolchain. "
@@ -73,50 +105,33 @@ if (NOT CMAKE_C_COMPILER)
                     "In order to rectify this, the build tree must be regenerated after installing ccache.")
             endif ()
         endif ()
-        if (NOT $ENV{PATH} MATCHES ${PATH} AND NOT COMPILER_PREFIX STREQUAL ARM_PREFIX)
+        if (NOT ARM_COMPILER_PREFIX STREQUAL ARM_PREFIX AND NOT $ENV{PATH} MATCHES ${PATH})
             message (FATAL_ERROR "The bin directory containing the compiler toolchain (${PATH}) has not been added in the PATH environment variable. "
                 "This is required to enable ccache support for ARM compiler toolchain.")
         endif ()
     endif ()
+    set (ARM_COMPILER_PREFIX ${ARM_COMPILER_PREFIX} CACHE INTERNAL "Path to C/C++ compiler tool symlinks or to the actual tools if not using ccache")
 endif ()
-set (CMAKE_C_COMPILER   ${COMPILER_PREFIX}-gcc CACHE PATH "C compiler")
-set (CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++ CACHE PATH "C++ compiler")
-set (CMAKE_STRIP        ${ARM_PREFIX}-strip    CACHE PATH "strip")
-set (CMAKE_AR           ${ARM_PREFIX}-ar       CACHE PATH "archive")
-set (CMAKE_LINKER       ${ARM_PREFIX}-ld       CACHE PATH "linker")
-set (CMAKE_NM           ${ARM_PREFIX}-nm       CACHE PATH "nm")
-set (CMAKE_OBJCOPY      ${ARM_PREFIX}-objcopy  CACHE PATH "objcopy")
-set (CMAKE_OBJDUMP      ${ARM_PREFIX}-objdump  CACHE PATH "objdump")
-set (CMAKE_RANLIB       ${ARM_PREFIX}-ranlib   CACHE PATH "ranlib")
-
-# specify the system root
-if (NOT ARM_SYSROOT)
-    if (DEFINED ENV{ARM_SYSROOT})
-        file (TO_CMAKE_PATH $ENV{ARM_SYSROOT} ARM_SYSROOT)
-    endif ()
-    if (NOT EXISTS ${ARM_SYSROOT})
-        message (FATAL_ERROR "Could not find ARM system root. "
-            "Use ARM_SYSROOT environment variable or build option to specify the location of system root.")
-    endif ()
-    set (ARM_PREFIX ${ARM_PREFIX} CACHE STRING "Prefix path to ARM cross-compiler tools (ARM on Linux cross-compiling build only)" FORCE)
-    set (ARM_SYSROOT ${ARM_SYSROOT} CACHE PATH "Path to ARM system root (ARM on Linux cross-compiling build only)" FORCE)
-endif ()
-set (CMAKE_SYSROOT ${ARM_SYSROOT})
-
-# only search libraries and headers in the target directories
-set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set (CMAKE_C_COMPILER   ${ARM_COMPILER_PREFIX}-gcc CACHE PATH "C compiler")
+set (CMAKE_CXX_COMPILER ${ARM_COMPILER_PREFIX}-g++ CACHE PATH "C++ compiler")
+set (CMAKE_STRIP        ${ARM_PREFIX}-strip        CACHE PATH "strip")
+set (CMAKE_AR           ${ARM_PREFIX}-ar           CACHE PATH "archive")
+set (CMAKE_LINKER       ${ARM_PREFIX}-ld           CACHE PATH "linker")
+set (CMAKE_NM           ${ARM_PREFIX}-nm           CACHE PATH "nm")
+set (CMAKE_OBJCOPY      ${ARM_PREFIX}-objcopy      CACHE PATH "objcopy")
+set (CMAKE_OBJDUMP      ${ARM_PREFIX}-objdump      CACHE PATH "objdump")
+set (CMAKE_RANLIB       ${ARM_PREFIX}-ranlib       CACHE PATH "ranlib")
 
 # Workaround try_compile() limitation where it cannot yet see cache variables during initial configuration
-get_property(IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
 if (NOT IN_TRY_COMPILE)
     get_cmake_property (CACHE_VARIABLES CACHE_VARIABLES)
     foreach (VAR ${CACHE_VARIABLES})
         if (VAR MATCHES ^ARM_|CMAKE_CX*_COMPILER)
             set (ENV{${VAR}} ${${VAR}})
+            list (APPEND VARS ${VAR})
         endif ()
     endforeach ()
+    set (ENV{VARS} "${VARS}")   # Stringify to keep the list together
 endif ()
 
 set (ARM 1)

+ 76 - 61
CMake/Toolchains/emscripten.toolchain.cmake

@@ -20,12 +20,27 @@
 # THE SOFTWARE.
 #
 
-# Save the original values of CC and CXX environment variables before they get altered by CMake later
-if (DEFINED CMAKE_CROSSCOMPILING)
-    return ()
+# Workaround try_compile() limitation where it cannot yet see cache variables during initial configuration
+get_property (IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
+if (IN_TRY_COMPILE)
+    foreach (VAR $ENV{VARS})
+        set (${VAR} $ENV{${VAR}})
+    endforeach ()
 else ()
-    set (SAVED_CC $ENV{CC})
-    set (SAVED_CXX $ENV{CXX})
+    # Prevent critical variables from changing after the initial configuration
+    if (CMAKE_CROSSCOMPILING)
+        set (SAVED_EMSCRIPTEN_ROOT_PATH ${EMSCRIPTEN_ROOT_PATH} CACHE INTERNAL "Initial value for EMSCRIPTEN_ROOT_PATH")
+        set (SAVED_EMSCRIPTEN_SYSROOT ${EMSCRIPTEN_SYSROOT} CACHE INTERNAL "Initial value for EMSCRIPTEN_SYSROOT")
+        # Save the initial values of CC and CXX environment variables
+        set (SAVED_CC $ENV{CC} CACHE INTERNAL "Initial value for CC")
+        set (SAVED_CXX $ENV{CXX} CACHE INTERNAL "Initial value for CXX")
+        return ()
+    elseif ((SAVED_EMSCRIPTEN_ROOT_PATH AND NOT SAVED_EMSCRIPTEN_ROOT_PATH STREQUAL EMSCRIPTEN_ROOT_PATH) OR (SAVED_EMSCRIPTEN_SYSROOT AND NOT SAVED_EMSCRIPTEN_SYSROOT STREQUAL EMSCRIPTEN_SYSROOT))
+        set (EMSCRIPTEN_ROOT_PATH ${SAVED_EMSCRIPTEN_ROOT_PATH} CACHE STRING "Root path to Emscripten cross-compiler tools (Emscripten only)" FORCE)
+        set (EMSCRIPTEN_SYSROOT ${SAVED_EMSCRIPTEN_SYSROOT} CACHE PATH "Path to Emscripten system root (Emscripten only)" FORCE)
+        message (FATAL_ERROR "EMSCRIPTEN_ROOT_PATH and EMSCRIPTEN_SYSROOT cannot be changed after the initial configuration/generation. "
+            "If you wish to change that then the build tree would have to be regenerated from scratch. Auto reverting to its initial value.")
+    endif ()
 endif ()
 
 # Reference toolchain variable to suppress "unused variable" warning
@@ -33,51 +48,70 @@ if (CMAKE_TOOLCHAIN_FILE)
     mark_as_advanced (CMAKE_TOOLCHAIN_FILE)
 endif ()
 
-# this one is important
+# This one is important
 set (CMAKE_SYSTEM_NAME Linux)
-# this one not so much
+# This one not so much
 set (CMAKE_SYSTEM_VERSION 1)
 
-# specify the cross compiler
-if (CMAKE_HOST_WIN32)
-    set (TOOL_EXT .bat)
-endif ()
-if (NOT EMSCRIPTEN_ROOT_PATH)
-    if (DEFINED ENV{EMSCRIPTEN_ROOT_PATH})
-        file (TO_CMAKE_PATH $ENV{EMSCRIPTEN_ROOT_PATH} EMSCRIPTEN_ROOT_PATH)
-    elseif (DEFINED ENV{EMSCRIPTEN})
-        file (TO_CMAKE_PATH $ENV{EMSCRIPTEN} EMSCRIPTEN_ROOT_PATH)
+# System root
+if (NOT IN_TRY_COMPILE)
+    if (NOT SAVED_EMSCRIPTEN_ROOT_PATH)
+        if (NOT EMSCRIPTEN_ROOT_PATH)
+            if (DEFINED ENV{EMSCRIPTEN_ROOT_PATH})
+                file (TO_CMAKE_PATH $ENV{EMSCRIPTEN_ROOT_PATH} EMSCRIPTEN_ROOT_PATH)
+            elseif (DEFINED ENV{EMSCRIPTEN})
+                file (TO_CMAKE_PATH $ENV{EMSCRIPTEN} EMSCRIPTEN_ROOT_PATH)
+            endif ()
+        endif ()
+        set (EMSCRIPTEN_ROOT_PATH ${EMSCRIPTEN_ROOT_PATH} CACHE STRING "Root path to Emscripten cross-compiler tools (Emscripten only)")
+        if (NOT EXISTS ${EMSCRIPTEN_ROOT_PATH}/emcc${TOOL_EXT})
+            message (FATAL_ERROR "Could not find Emscripten cross compilation tool. "
+                "Use EMSCRIPTEN_ROOT_PATH environment variable or build option to specify the location of the toolchain. "
+                "Or use the canonical EMSCRIPTEN environment variable by calling emsdk_env script.")
+        endif ()
+    endif ()
+    if (NOT SAVED_EMSCRIPTEN_SYSROOT)
+        if (NOT EMSCRIPTEN_SYSROOT)
+            if (DEFINED ENV{EMSCRIPTEN_SYSROOT})
+                file (TO_CMAKE_PATH $ENV{EMSCRIPTEN_SYSROOT} EMSCRIPTEN_SYSROOT)
+            else ()
+                set (EMSCRIPTEN_SYSROOT ${EMSCRIPTEN_ROOT_PATH}/system)
+            endif ()
+        endif ()
+        set (EMSCRIPTEN_SYSROOT ${EMSCRIPTEN_SYSROOT} CACHE PATH "Path to Emscripten system root (Emscripten only)")
+        if (NOT EXISTS ${EMSCRIPTEN_SYSROOT})
+            message (FATAL_ERROR "Could not find Emscripten system root. "
+                "Use EMSCRIPTEN_SYSROOT environment variable or build option to specify the location of system root.")
+        endif ()
     endif ()
 endif ()
-if (NOT EXISTS ${EMSCRIPTEN_ROOT_PATH}/emcc${TOOL_EXT})
-    message (FATAL_ERROR "Could not find Emscripten cross compilation tool. "
-        "Use EMSCRIPTEN_ROOT_PATH environment variable or build option to specify the location of the toolchain. "
-        "Or use the canonical EMSCRIPTEN environment variable by calling emsdk_env script.")
+set (CMAKE_SYSROOT ${EMSCRIPTEN_SYSROOT})
+# Only search libraries and headers in sysroot
+set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+# Cross compiler tools
+if (CMAKE_HOST_WIN32)
+    set (TOOL_EXT .bat)
 endif ()
 if (NOT EMSCRIPTEN_EMCC_VERSION)
-    if (DEFINED ENV{EMSCRIPTEN_EMCC_VERSION})
-        set (EMSCRIPTEN_EMCC_VERSION $ENV{EMSCRIPTEN_EMCC_VERSION})
+    execute_process (COMMAND ${EMSCRIPTEN_ROOT_PATH}/emcc${TOOL_EXT} --version RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE EMSCRIPTEN_EMCC_VERSION ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (EXIT_CODE EQUAL 0)
+        string (REGEX MATCH "[^ .]+\\.[^.]+\\.[^ ]+" EMSCRIPTEN_EMCC_VERSION "${EMSCRIPTEN_EMCC_VERSION}")
     else ()
-        execute_process (COMMAND ${EMSCRIPTEN_ROOT_PATH}/emcc${TOOL_EXT} --version RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE EMSCRIPTEN_EMCC_VERSION ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
-        if (EXIT_CODE EQUAL 0)
-            string (REGEX MATCH "[^ .]+\\.[^.]+\\.[^ ]+" EMSCRIPTEN_EMCC_VERSION "${EMSCRIPTEN_EMCC_VERSION}")
-        else ()
-            message (FATAL_ERROR "Could not determine the emcc version. Make sure you have installed and activated the Emscripten SDK correctly.")
-        endif ()
+        message (FATAL_ERROR "Could not determine the emcc version. Make sure you have installed and activated the Emscripten SDK correctly.")
     endif ()
     set (EMSCRIPTEN_EMCC_VERSION ${EMSCRIPTEN_EMCC_VERSION} CACHE INTERNAL "emcc version being used in this build tree")
 endif ()
-set (COMPILER_PATH ${EMSCRIPTEN_ROOT_PATH})
 # ccache support could only be enabled for emcc prior to 1.31.3 when the CCACHE_CPP2 env var is also set to 1, newer emcc version could enable ccache support without this caveat (see https://github.com/kripken/emscripten/issues/3365 for more detail)
 # The CCACHE_CPP2 env var tells ccache to fallback to use original input source file instead of preprocessed one when passing on the compilation task to the compiler proper
-if (NOT CMAKE_C_COMPILER)
-    if (DEFINED ENV{CMAKE_C_COMPILER} AND DEFINED ENV{CMAKE_CXX_COMPILER})
-        set (CMAKE_C_COMPILER $ENV{CMAKE_C_COMPILER})
-        set (CMAKE_CXX_COMPILER $ENV{CMAKE_CXX_COMPILER})
-    elseif ("$ENV{USE_CCACHE}" AND NOT CMAKE_HOST_WIN32 AND ("$ENV{CCACHE_CPP2}" OR NOT EMSCRIPTEN_EMCC_VERSION VERSION_LESS 1.31.3))
+if (NOT EMSCRIPTEN_COMPILER_PATH)
+    set (EMSCRIPTEN_COMPILER_PATH ${EMSCRIPTEN_ROOT_PATH})
+    if ("$ENV{USE_CCACHE}" AND NOT CMAKE_HOST_WIN32 AND ("$ENV{CCACHE_CPP2}" OR NOT EMSCRIPTEN_EMCC_VERSION VERSION_LESS 1.31.3))
         execute_process (COMMAND whereis -b ccache COMMAND grep -o \\S*lib\\S* OUTPUT_VARIABLE CCACHE_SYMLINK ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
         if (CCACHE_SYMLINK AND EXISTS ${CCACHE_SYMLINK}/emcc AND EXISTS ${CCACHE_SYMLINK}/em++)
-            set (COMPILER_PATH ${CCACHE_SYMLINK})
+            set (EMSCRIPTEN_COMPILER_PATH ${CCACHE_SYMLINK})
         else ()
             # Fallback to create the ccache symlink in the build tree itself
             execute_process (COMMAND which ccache RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE CCACHE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -85,7 +119,7 @@ if (NOT CMAKE_C_COMPILER)
                 foreach (TOOL emcc em++)
                     execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${TOOL})
                 endforeach ()
-                set (COMPILER_PATH ${CMAKE_BINARY_DIR})
+                set (EMSCRIPTEN_COMPILER_PATH ${CMAKE_BINARY_DIR})
             else ()
                 message (WARNING "ccache may not have been installed on this host system. "
                     "This is required to enable ccache support for Emscripten compiler toolchain. "
@@ -93,14 +127,15 @@ if (NOT CMAKE_C_COMPILER)
                     "In order to rectify this, the build tree must be regenerated after installing ccache.")
             endif ()
         endif ()
-        if (NOT $ENV{PATH} MATCHES ${EMSCRIPTEN_ROOT_PATH} AND NOT COMPILER_PATH STREQUAL EMSCRIPTEN_ROOT_PATH)
+        if (NOT EMSCRIPTEN_COMPILER_PATH STREQUAL EMSCRIPTEN_ROOT_PATH AND NOT $ENV{PATH} MATCHES ${EMSCRIPTEN_ROOT_PATH})
             message (FATAL_ERROR "The bin directory containing the compiler toolchain (${EMSCRIPTEN_ROOT_PATH}) has not been added in the PATH environment variable. "
                 "This is required to enable ccache support for Emscripten compiler toolchain.")
         endif ()
     endif ()
+    set (EMSCRIPTEN_COMPILER_PATH ${EMSCRIPTEN_COMPILER_PATH} CACHE INTERNAL "Path to C/C++ compiler tool symlinks or to the actual tools if not using ccache")
 endif ()
-set (CMAKE_C_COMPILER   ${COMPILER_PATH}/emcc${TOOL_EXT}            CACHE PATH "C compiler")
-set (CMAKE_CXX_COMPILER ${COMPILER_PATH}/em++${TOOL_EXT}            CACHE PATH "C++ compiler")
+set (CMAKE_C_COMPILER   ${EMSCRIPTEN_COMPILER_PATH}/emcc${TOOL_EXT} CACHE PATH "C compiler")
+set (CMAKE_CXX_COMPILER ${EMSCRIPTEN_COMPILER_PATH}/em++${TOOL_EXT} CACHE PATH "C++ compiler")
 set (CMAKE_AR           ${EMSCRIPTEN_ROOT_PATH}/emar${TOOL_EXT}     CACHE PATH "archive")
 set (CMAKE_RANLIB       ${EMSCRIPTEN_ROOT_PATH}/emranlib${TOOL_EXT} CACHE PATH "ranlib")
 set (CMAKE_LINKER       ${EMSCRIPTEN_ROOT_PATH}/emlink.py           CACHE PATH "linker")
@@ -109,27 +144,6 @@ set (EMRUN              ${EMSCRIPTEN_ROOT_PATH}/emrun${TOOL_EXT}    CACHE PATH "
 set (EMPACKAGER         python ${EMSCRIPTEN_ROOT_PATH}/tools/file_packager.py CACHE PATH "file_packager.py")
 set (EMBUILDER          python ${EMSCRIPTEN_ROOT_PATH}/embuilder.py CACHE PATH "embuilder.py")
 
-# specify the system root
-if (NOT EMSCRIPTEN_SYSROOT)
-    if (DEFINED ENV{EMSCRIPTEN_SYSROOT})
-        file (TO_CMAKE_PATH $ENV{EMSCRIPTEN_SYSROOT} EMSCRIPTEN_SYSROOT)
-    else ()
-        set (EMSCRIPTEN_SYSROOT ${EMSCRIPTEN_ROOT_PATH}/system)
-    endif ()
-    if (NOT EXISTS ${EMSCRIPTEN_SYSROOT})
-        message (FATAL_ERROR "Could not find Emscripten system root. "
-            "Use EMSCRIPTEN_SYSROOT environment variable or build option to specify the location of system root.")
-    endif ()
-    set (EMSCRIPTEN_ROOT_PATH ${EMSCRIPTEN_ROOT_PATH} CACHE STRING "Root path to Emscripten cross-compiler tools (Emscripten only)" FORCE)
-    set (EMSCRIPTEN_SYSROOT ${EMSCRIPTEN_SYSROOT} CACHE PATH "Path to Emscripten system root (Emscripten only)" FORCE)
-endif ()
-set (CMAKE_FIND_ROOT_PATH ${EMSCRIPTEN_SYSROOT})
-
-# only search libraries and headers in the target directories
-set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
 # Still perform the compiler checks except for those stated otherwise below
 foreach (LANG C CXX)
     # Since currently CMake does not able to identify Emscripten compiler toolchain, set the compiler identification explicitly
@@ -159,14 +173,15 @@ if (CMAKE_HOST_WIN32)
 endif ()
 
 # Workaround try_compile() limitation where it cannot yet see cache variables during initial configuration
-get_property(IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
 if (NOT IN_TRY_COMPILE)
     get_cmake_property (CACHE_VARIABLES CACHE_VARIABLES)
     foreach (VAR ${CACHE_VARIABLES})
         if (VAR MATCHES ^EMSCRIPTEN_|CMAKE_CX*_COMPILER)
             set (ENV{${VAR}} ${${VAR}})
+            list (APPEND VARS ${VAR})
         endif ()
     endforeach ()
+    set (ENV{VARS} "${VARS}")   # Stringify to keep the list together
 endif ()
 
 set (WEB 1)

+ 66 - 49
CMake/Toolchains/mingw.toolchain.cmake

@@ -20,12 +20,27 @@
 # THE SOFTWARE.
 #
 
-# Save the original values of CC and CXX environment variables before they get altered by CMake later
-if (DEFINED CMAKE_CROSSCOMPILING)
-    return ()
+# Workaround try_compile() limitation where it cannot yet see cache variables during initial configuration
+get_property (IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
+if (IN_TRY_COMPILE)
+    foreach (VAR $ENV{VARS})
+        set (${VAR} $ENV{${VAR}})
+    endforeach ()
 else ()
-    set (SAVED_CC $ENV{CC})
-    set (SAVED_CXX $ENV{CXX})
+    # Prevent critical variables from changing after the initial configuration
+    if (CMAKE_CROSSCOMPILING)
+        set (SAVED_MINGW_SYSROOT ${MINGW_SYSROOT} CACHE INTERNAL "Initial value for MINGW_SYSROOT")
+        set (SAVED_MINGW_PREFIX ${MINGW_PREFIX} CACHE INTERNAL "Initial value for MINGW_PREFIX")
+        # Save the initial values of CC and CXX environment variables
+        set (SAVED_CC $ENV{CC} CACHE INTERNAL "Initial value for CC")
+        set (SAVED_CXX $ENV{CXX} CACHE INTERNAL "Initial value for CXX")
+        return ()
+    elseif ((SAVED_MINGW_SYSROOT AND NOT SAVED_MINGW_SYSROOT STREQUAL MINGW_SYSROOT) OR (SAVED_MINGW_PREFIX AND NOT SAVED_MINGW_PREFIX STREQUAL MINGW_PREFIX))
+        set (MINGW_SYSROOT ${SAVED_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)
+        set (MINGW_PREFIX ${SAVED_MINGW_PREFIX} CACHE STRING "Prefix path to MinGW cross-compiler tools (MinGW cross-compiling build only)" FORCE)
+        message (FATAL_ERROR "MINGW_SYSROOT and MINGW_PREFIX cannot be changed after the initial configuration/generation. "
+            "If you wish to change that then the build tree would have to be regenerated from scratch. Auto reverting to its initial value.")
+    endif ()
 endif ()
 
 # Reference toolchain variable to suppress "unused variable" warning
@@ -33,31 +48,31 @@ if (CMAKE_TOOLCHAIN_FILE)
     mark_as_advanced (CMAKE_TOOLCHAIN_FILE)
 endif ()
 
-# this one is important
+# This one is important
 set (CMAKE_SYSTEM_NAME Windows)
-# this one not so much
+# This one not so much
 set (CMAKE_SYSTEM_PROCESSOR x86)
 set (CMAKE_SYSTEM_VERSION 1)
 
-# specify the cross compiler
-if (NOT MINGW_PREFIX AND DEFINED ENV{MINGW_PREFIX})
-    file (TO_CMAKE_PATH $ENV{MINGW_PREFIX} MINGW_PREFIX)
-endif ()
-if (NOT EXISTS ${MINGW_PREFIX}-gcc)
-    message (FATAL_ERROR "Could not find MinGW cross compilation tool. "
-        "Use MINGW_PREFIX environment variable or build option to specify the location of the toolchain.")
+# Cross compiler tools
+if (NOT IN_TRY_COMPILE AND NOT SAVED_MINGW_PREFIX)
+    if (NOT MINGW_PREFIX AND DEFINED ENV{MINGW_PREFIX})
+        file (TO_CMAKE_PATH $ENV{MINGW_PREFIX} MINGW_PREFIX)
+    endif ()
+    set (MINGW_PREFIX ${MINGW_PREFIX} CACHE STRING "Prefix path to MinGW cross-compiler tools (MinGW cross-compiling build only)")
+    if (NOT EXISTS ${MINGW_PREFIX}-gcc)
+        message (FATAL_ERROR "Could not find MinGW cross compilation tool. "
+            "Use MINGW_PREFIX environment variable or build option to specify the location of the toolchain.")
+    endif ()
 endif ()
-set (COMPILER_PREFIX ${MINGW_PREFIX})
-if (NOT CMAKE_C_COMPILER)
-    if (DEFINED ENV{CMAKE_C_COMPILER} AND DEFINED ENV{CMAKE_CXX_COMPILER})
-        set (CMAKE_C_COMPILER $ENV{CMAKE_C_COMPILER})
-        set (CMAKE_CXX_COMPILER $ENV{CMAKE_CXX_COMPILER})
-    elseif ("$ENV{USE_CCACHE}")
+if (NOT MINGW_COMPILER_PREFIX)
+    set (MINGW_COMPILER_PREFIX ${MINGW_PREFIX})
+    if ("$ENV{USE_CCACHE}")
         get_filename_component (PATH ${MINGW_PREFIX} PATH)
         get_filename_component (NAME ${MINGW_PREFIX} NAME)
         execute_process (COMMAND whereis -b ccache COMMAND grep -o \\S*lib\\S* OUTPUT_VARIABLE CCACHE_SYMLINK ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
         if (CCACHE_SYMLINK AND EXISTS ${CCACHE_SYMLINK}/${NAME}-gcc AND EXISTS ${CCACHE_SYMLINK}/${NAME}-g++)
-            set (COMPILER_PREFIX ${CCACHE_SYMLINK}/${NAME})
+            set (MINGW_COMPILER_PREFIX ${CCACHE_SYMLINK}/${NAME})
         else ()
             # Fallback to create the ccache symlink in the build tree itself
             execute_process (COMMAND which ccache RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE CCACHE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -65,7 +80,7 @@ if (NOT CMAKE_C_COMPILER)
                 foreach (TOOL gcc g++)
                     execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${NAME}-${TOOL})
                 endforeach ()
-                set (COMPILER_PREFIX ${CMAKE_BINARY_DIR}/${NAME})
+                set (MINGW_COMPILER_PREFIX ${CMAKE_BINARY_DIR}/${NAME})
             else ()
                 message (WARNING "ccache may not have been installed on this host system. "
                     "This is required to enable ccache support for MinGW compiler toolchain. "
@@ -73,55 +88,57 @@ if (NOT CMAKE_C_COMPILER)
                     "In order to rectify this, the build tree must be regenerated after installing ccache.")
             endif ()
         endif ()
-        if (NOT $ENV{PATH} MATCHES ${PATH} AND NOT COMPILER_PREFIX STREQUAL MINGW_PREFIX)
+        if (NOT MINGW_COMPILER_PREFIX STREQUAL MINGW_PREFIX AND NOT $ENV{PATH} MATCHES ${PATH})
             message (FATAL_ERROR "The bin directory containing the compiler toolchain (${PATH}) has not been added in the PATH environment variable. "
                 "This is required to enable ccache support for MinGW compiler toolchain.")
         endif ()
     endif ()
+    set (MINGW_COMPILER_PREFIX ${MINGW_COMPILER_PREFIX} CACHE INTERNAL "Path to C/C++ compiler tool symlinks or to the actual tools if not using ccache")
 endif ()
-set (CMAKE_C_COMPILER   ${COMPILER_PREFIX}-gcc  CACHE PATH "C compiler")
-set (CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++  CACHE PATH "C++ compiler")
-set (CMAKE_STRIP        ${MINGW_PREFIX}-strip   CACHE PATH "strip")
-set (CMAKE_AR           ${MINGW_PREFIX}-ar      CACHE PATH "archive")
-set (CMAKE_LINKER       ${MINGW_PREFIX}-ld      CACHE PATH "linker")
-set (CMAKE_NM           ${MINGW_PREFIX}-nm      CACHE PATH "nm")
-set (CMAKE_OBJCOPY      ${MINGW_PREFIX}-objcopy CACHE PATH "objcopy")
-set (CMAKE_OBJDUMP      ${MINGW_PREFIX}-objdump CACHE PATH "objdump")
-set (CMAKE_RANLIB       ${MINGW_PREFIX}-ranlib  CACHE PATH "ranlib")
-set (CMAKE_RC_COMPILER  ${MINGW_PREFIX}-windres CACHE PATH "RC compiler")
+set (CMAKE_C_COMPILER   ${MINGW_COMPILER_PREFIX}-gcc CACHE PATH "C compiler")
+set (CMAKE_CXX_COMPILER ${MINGW_COMPILER_PREFIX}-g++ CACHE PATH "C++ compiler")
+set (CMAKE_STRIP        ${MINGW_PREFIX}-strip        CACHE PATH "strip")
+set (CMAKE_AR           ${MINGW_PREFIX}-ar           CACHE PATH "archive")
+set (CMAKE_LINKER       ${MINGW_PREFIX}-ld           CACHE PATH "linker")
+set (CMAKE_NM           ${MINGW_PREFIX}-nm           CACHE PATH "nm")
+set (CMAKE_OBJCOPY      ${MINGW_PREFIX}-objcopy      CACHE PATH "objcopy")
+set (CMAKE_OBJDUMP      ${MINGW_PREFIX}-objdump      CACHE PATH "objdump")
+set (CMAKE_RANLIB       ${MINGW_PREFIX}-ranlib       CACHE PATH "ranlib")
+set (CMAKE_RC_COMPILER  ${MINGW_PREFIX}-windres      CACHE PATH "RC compiler")
 
-# specify the system root
-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 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)
+# System root
+if (NOT IN_TRY_COMPILE AND NOT SAVED_MINGW_SYSROOT)
+    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 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 ()
     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")
     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_PREFIX ${MINGW_PREFIX} CACHE STRING "Prefix path to MinGW cross-compiler tools (MinGW cross-compiling build only)" FORCE)
-    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 ()
-set (CMAKE_FIND_ROOT_PATH ${MINGW_SYSROOT})
-
-# only search libraries and headers in the target directories
+set (CMAKE_FIND_ROOT_PATH ${MINGW_SYSROOT})     # Intentionally do not use CMAKE_SYSROOT because it does not work for MinGW compiler toolchain
+# Only search libraries and headers in sysroot
 set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
 set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
 set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 
 # Workaround try_compile() limitation where it cannot yet see cache variables during initial configuration
-get_property(IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
 if (NOT IN_TRY_COMPILE)
     get_cmake_property (CACHE_VARIABLES CACHE_VARIABLES)
     foreach (VAR ${CACHE_VARIABLES})
         if (VAR MATCHES ^MINGW_|CMAKE_CX*_COMPILER)
             set (ENV{${VAR}} ${${VAR}})
+            list (APPEND VARS ${VAR})
         endif ()
     endforeach ()
+    set (ENV{VARS} "${VARS}")   # Stringify to keep the list together
 endif ()

+ 66 - 51
CMake/Toolchains/raspberrypi.toolchain.cmake

@@ -20,12 +20,27 @@
 # THE SOFTWARE.
 #
 
-# Save the original values of CC and CXX environment variables before they get altered by CMake later
-if (DEFINED CMAKE_CROSSCOMPILING)
-    return ()
+# Workaround try_compile() limitation where it cannot yet see cache variables during initial configuration
+get_property (IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
+if (IN_TRY_COMPILE)
+    foreach (VAR $ENV{VARS})
+        set (${VAR} $ENV{${VAR}})
+    endforeach ()
 else ()
-    set (SAVED_CC $ENV{CC})
-    set (SAVED_CXX $ENV{CXX})
+    # Prevent critical variables from changing after the initial configuration
+    if (CMAKE_CROSSCOMPILING)
+        set (SAVED_RPI_SYSROOT ${RPI_SYSROOT} CACHE INTERNAL "Initial value for RPI_SYSROOT")
+        set (SAVED_RPI_PREFIX ${RPI_PREFIX} CACHE INTERNAL "Initial value for RPI_PREFIX")
+        # Save the initial values of CC and CXX environment variables
+        set (SAVED_CC $ENV{CC} CACHE INTERNAL "Initial value for CC")
+        set (SAVED_CXX $ENV{CXX} CACHE INTERNAL "Initial value for CXX")
+        return ()
+    elseif ((SAVED_RPI_SYSROOT AND NOT SAVED_RPI_SYSROOT STREQUAL RPI_SYSROOT) OR (SAVED_RPI_PREFIX AND NOT SAVED_RPI_PREFIX STREQUAL RPI_PREFIX))
+        set (RPI_SYSROOT ${SAVED_RPI_SYSROOT} CACHE PATH "Path to Raspberry Pi system root (RPI cross-compiling build only)" FORCE)
+        set (RPI_PREFIX ${SAVED_RPI_PREFIX} CACHE STRING "Prefix path to Raspberry Pi cross-compiler tools (RPI cross-compiling build only)" FORCE)
+        message (FATAL_ERROR "RPI_SYSROOT and RPI_PREFIX cannot be changed after the initial configuration/generation. "
+            "If you wish to change that then the build tree would have to be regenerated from scratch. Auto reverting to its initial value.")
+    endif ()
 endif ()
 
 # Reference toolchain variable to suppress "unused variable" warning
@@ -33,31 +48,48 @@ if (CMAKE_TOOLCHAIN_FILE)
     mark_as_advanced (CMAKE_TOOLCHAIN_FILE)
 endif ()
 
-# this one is important
+# This one is important
 set (CMAKE_SYSTEM_NAME Linux)
-# this one not so much
+# This one not so much
 set (CMAKE_SYSTEM_PROCESSOR arm)
 set (CMAKE_SYSTEM_VERSION 1)
 
-# specify the cross compiler
-if (NOT RPI_PREFIX AND DEFINED ENV{RPI_PREFIX})
-    file (TO_CMAKE_PATH $ENV{RPI_PREFIX} RPI_PREFIX)
+# System root
+if (NOT IN_TRY_COMPILE AND NOT SAVED_RPI_SYSROOT)
+    if (NOT RPI_SYSROOT AND DEFINED ENV{RPI_SYSROOT})
+        file (TO_CMAKE_PATH $ENV{RPI_SYSROOT} RPI_SYSROOT)
+    endif ()
+    set (RPI_SYSROOT ${RPI_SYSROOT} CACHE PATH "Path to Raspberry Pi system root (RPI cross-compiling build only)")
+    if (NOT EXISTS ${RPI_SYSROOT})
+        message (FATAL_ERROR "Could not find Raspberry Pi system root. "
+            "Use RPI_SYSROOT environment variable or build option to specify the location of system root.")
+    endif ()
 endif ()
-if (NOT EXISTS ${RPI_PREFIX}-gcc)
-    message (FATAL_ERROR "Could not find Raspberry Pi cross compilation tool. "
-        "Use RPI_PREFIX environment variable or build option to specify the location of the toolchain.")
+set (CMAKE_SYSROOT ${RPI_SYSROOT})
+# Only search libraries and headers in sysroot
+set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+# Cross compiler tools
+if (NOT IN_TRY_COMPILE AND NOT SAVED_RPI_PREFIX)
+    if (NOT RPI_PREFIX AND DEFINED ENV{RPI_PREFIX})
+        file (TO_CMAKE_PATH $ENV{RPI_PREFIX} RPI_PREFIX)
+    endif ()
+    set (RPI_PREFIX ${RPI_PREFIX} CACHE STRING "Prefix path to Raspberry Pi cross-compiler tools (RPI cross-compiling build only)")
+    if (NOT EXISTS ${RPI_PREFIX}-gcc)
+        message (FATAL_ERROR "Could not find Raspberry Pi cross compilation tool. "
+            "Use RPI_PREFIX environment variable or build option to specify the location of the toolchain.")
+    endif ()
 endif ()
-set (COMPILER_PREFIX ${RPI_PREFIX})
-if (NOT CMAKE_C_COMPILER)
-    if (DEFINED ENV{CMAKE_C_COMPILER} AND DEFINED ENV{CMAKE_CXX_COMPILER})
-        set (CMAKE_C_COMPILER $ENV{CMAKE_C_COMPILER})
-        set (CMAKE_CXX_COMPILER $ENV{CMAKE_CXX_COMPILER})
-    elseif ("$ENV{USE_CCACHE}")
+if (NOT RPI_COMPILER_PREFIX)
+    set (RPI_COMPILER_PREFIX ${RPI_PREFIX})
+    if ("$ENV{USE_CCACHE}")
         get_filename_component (PATH ${RPI_PREFIX} PATH)
         get_filename_component (NAME ${RPI_PREFIX} NAME)
         execute_process (COMMAND whereis -b ccache COMMAND grep -o \\S*lib\\S* OUTPUT_VARIABLE CCACHE_SYMLINK ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
         if (CCACHE_SYMLINK AND EXISTS ${CCACHE_SYMLINK}/${NAME}-gcc AND EXISTS ${CCACHE_SYMLINK}/${NAME}-g++)
-            set (COMPILER_PREFIX ${CCACHE_SYMLINK}/${NAME})
+            set (RPI_COMPILER_PREFIX ${CCACHE_SYMLINK}/${NAME})
         else ()
             # Fallback to create the ccache symlink in the build tree itself
             execute_process (COMMAND which ccache RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE CCACHE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -65,7 +97,7 @@ if (NOT CMAKE_C_COMPILER)
                 foreach (TOOL gcc g++)
                     execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${NAME}-${TOOL})
                 endforeach ()
-                set (COMPILER_PREFIX ${CMAKE_BINARY_DIR}/${NAME})
+                set (RPI_COMPILER_PREFIX ${CMAKE_BINARY_DIR}/${NAME})
             else ()
                 message (WARNING "ccache may not have been installed on this host system. "
                     "This is required to enable ccache support for Raspberry-Pi compiler toolchain. "
@@ -73,50 +105,33 @@ if (NOT CMAKE_C_COMPILER)
                     "In order to rectify this, the build tree must be regenerated after installing ccache.")
             endif ()
         endif ()
-        if (NOT $ENV{PATH} MATCHES ${PATH} AND NOT COMPILER_PREFIX STREQUAL RPI_PREFIX)
+        if (NOT RPI_COMPILER_PREFIX STREQUAL RPI_PREFIX AND NOT $ENV{PATH} MATCHES ${PATH})
             message (FATAL_ERROR "The bin directory containing the compiler toolchain (${PATH}) has not been added in the PATH environment variable. "
                 "This is required to enable ccache support for Raspberry-Pi compiler toolchain.")
         endif ()
     endif ()
+    set (RPI_COMPILER_PREFIX ${RPI_COMPILER_PREFIX} CACHE INTERNAL "Path to C/C++ compiler tool symlinks or to the actual tools if not using ccache")
 endif ()
-set (CMAKE_C_COMPILER   ${COMPILER_PREFIX}-gcc CACHE PATH "C compiler")
-set (CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++ CACHE PATH "C++ compiler")
-set (CMAKE_STRIP        ${RPI_PREFIX}-strip    CACHE PATH "strip")
-set (CMAKE_AR           ${RPI_PREFIX}-ar       CACHE PATH "archive")
-set (CMAKE_LINKER       ${RPI_PREFIX}-ld       CACHE PATH "linker")
-set (CMAKE_NM           ${RPI_PREFIX}-nm       CACHE PATH "nm")
-set (CMAKE_OBJCOPY      ${RPI_PREFIX}-objcopy  CACHE PATH "objcopy")
-set (CMAKE_OBJDUMP      ${RPI_PREFIX}-objdump  CACHE PATH "objdump")
-set (CMAKE_RANLIB       ${RPI_PREFIX}-ranlib   CACHE PATH "ranlib")
-
-# specify the system root
-if (NOT RPI_SYSROOT OR NOT VIDEOCORE_INCLUDE_DIRS OR NOT VIDEOCORE_LIBRARIES)
-    if (DEFINED ENV{RPI_SYSROOT})
-        file (TO_CMAKE_PATH $ENV{RPI_SYSROOT} RPI_SYSROOT)
-    endif ()
-    if (NOT EXISTS ${RPI_SYSROOT})
-        message (FATAL_ERROR "Could not find Raspberry Pi system root. "
-            "Use RPI_SYSROOT environment variable or build option to specify the location of system root.")
-    endif ()
-    set (RPI_PREFIX ${RPI_PREFIX} CACHE STRING "Prefix path to Raspberry Pi cross-compiler tools (RPI cross-compiling build only)" FORCE)
-    set (RPI_SYSROOT ${RPI_SYSROOT} CACHE PATH "Path to Raspberry Pi system root (RPI cross-compiling build only)" FORCE)
-endif ()
-set (CMAKE_SYSROOT ${RPI_SYSROOT})
-
-# only search libraries and headers in the target directories
-set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set (CMAKE_C_COMPILER   ${RPI_COMPILER_PREFIX}-gcc CACHE PATH "C compiler")
+set (CMAKE_CXX_COMPILER ${RPI_COMPILER_PREFIX}-g++ CACHE PATH "C++ compiler")
+set (CMAKE_STRIP        ${RPI_PREFIX}-strip        CACHE PATH "strip")
+set (CMAKE_AR           ${RPI_PREFIX}-ar           CACHE PATH "archive")
+set (CMAKE_LINKER       ${RPI_PREFIX}-ld           CACHE PATH "linker")
+set (CMAKE_NM           ${RPI_PREFIX}-nm           CACHE PATH "nm")
+set (CMAKE_OBJCOPY      ${RPI_PREFIX}-objcopy      CACHE PATH "objcopy")
+set (CMAKE_OBJDUMP      ${RPI_PREFIX}-objdump      CACHE PATH "objdump")
+set (CMAKE_RANLIB       ${RPI_PREFIX}-ranlib       CACHE PATH "ranlib")
 
 # Workaround try_compile() limitation where it cannot yet see cache variables during initial configuration
-get_property(IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
 if (NOT IN_TRY_COMPILE)
     get_cmake_property (CACHE_VARIABLES CACHE_VARIABLES)
     foreach (VAR ${CACHE_VARIABLES})
         if (VAR MATCHES ^RPI_|CMAKE_CX*_COMPILER)
             set (ENV{${VAR}} ${${VAR}})
+            list (APPEND VARS ${VAR})
         endif ()
     endforeach ()
+    set (ENV{VARS} "${VARS}")   # Stringify to keep the list together
 endif ()
 
 set (RPI 1)