CI: Skip cmake reconfigure on Linux when cached build dir is valid

libeigen/eigen!2427

Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
diff --git a/ci/scripts/build.linux.script.sh b/ci/scripts/build.linux.script.sh
index 82d85a5..32ecbd4 100755
--- a/ci/scripts/build.linux.script.sh
+++ b/ci/scripts/build.linux.script.sh
@@ -7,12 +7,30 @@
 mkdir -p ${EIGEN_CI_BUILDDIR}
 cd ${EIGEN_CI_BUILDDIR}
 
-# Configure build.
-cmake -G Ninja                                                   \
-  -DCMAKE_CXX_COMPILER=${EIGEN_CI_CXX_COMPILER}                  \
-  -DCMAKE_C_COMPILER=${EIGEN_CI_C_COMPILER}                      \
-  -DCMAKE_CXX_COMPILER_TARGET=${EIGEN_CI_CXX_COMPILER_TARGET}    \
-  ${EIGEN_CI_ADDITIONAL_ARGS} ${rootdir}
+# Build the cmake configure command.
+cmake_args="-G Ninja \
+  -DCMAKE_CXX_COMPILER=${EIGEN_CI_CXX_COMPILER} \
+  -DCMAKE_C_COMPILER=${EIGEN_CI_C_COMPILER} \
+  -DCMAKE_CXX_COMPILER_TARGET=${EIGEN_CI_CXX_COMPILER_TARGET} \
+  ${EIGEN_CI_ADDITIONAL_ARGS}"
+
+# Skip cmake configure when the cached build directory already has a valid
+# build.ninja and the cmake arguments have not changed.  This avoids a full
+# reconfigure on Linux CI where compilers are installed via apt-get into
+# ephemeral containers — the fresh compiler binary has a different inode/mtime,
+# causing CMake to re-probe and regenerate everything, which invalidates
+# ninja's dependency tracking and forces a full rebuild.
+#
+# Ninja itself re-runs cmake automatically when CMakeLists.txt files change,
+# so skipping the explicit configure is safe.
+config_hash=$(echo "${cmake_args}" | sha256sum | cut -d' ' -f1)
+if [[ -s build.ninja && -f .cmake_config_hash && \
+      "$(cat .cmake_config_hash)" == "${config_hash}" ]]; then
+  echo "Cached build directory is valid (cmake args unchanged), skipping configure."
+else
+  cmake ${cmake_args} ${rootdir}
+  echo "${config_hash}" > .cmake_config_hash
+fi
 
 target=""
 if [[ ${EIGEN_CI_BUILD_TARGET} ]]; then