Browse Source

cmake: Add --fresh option to clear the cache and start from scratch

Simplify the workflow to re-run CMake from scratch as if a build tree
were never before processed, regardless of whether it has been.

Fixes: #23119
Brad King 3 years ago
parent
commit
9f1471739d

+ 7 - 0
Help/manual/cmake.1.rst

@@ -197,6 +197,13 @@ Options
 
 .. include:: OPTIONS_BUILD.txt
 
+``--fresh``
+ .. versionadded:: 3.24
+
+ Perform a fresh configuration of the build tree.
+ This removes any existing ``CMakeCache.txt`` file and associated
+ ``CMakeFiles/`` directory, and recreates them from scratch.
+
 ``-L[A][H]``
  List non-advanced cached variables.
 

+ 5 - 0
Help/release/dev/cmake-fresh.rst

@@ -0,0 +1,5 @@
+cmake-fresh
+-----------
+
+* :manual:`cmake(1)` gained the ``--fresh`` command-line option to remove
+  any existing ``CMakeCache.txt`` when configuring a build tree.

+ 12 - 0
Source/cmake.cxx

@@ -868,6 +868,11 @@ void cmake::SetArgs(const std::vector<std::string>& args)
     CommandArgument{ "-B", "No build directory specified for -B",
                      CommandArgument::Values::One,
                      CommandArgument::RequiresSeparator::No, BuildArgLambda },
+    CommandArgument{ "--fresh", CommandArgument::Values::Zero,
+                     [](std::string const&, cmake* cm) -> bool {
+                       cm->FreshCache = true;
+                       return true;
+                     } },
     CommandArgument{ "-P", "-P must be followed by a file name.",
                      CommandArgument::Values::One,
                      CommandArgument::RequiresSeparator::No,
@@ -2404,12 +2409,19 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
   }
 
   if (this->GetWorkingMode() == NORMAL_MODE) {
+    if (this->FreshCache) {
+      this->DeleteCache(this->GetHomeOutputDirectory());
+    }
     // load the cache
     if (this->LoadCache() < 0) {
       cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n");
       return -1;
     }
   } else {
+    if (this->FreshCache) {
+      cmSystemTools::Error("--fresh allowed only when configuring a project");
+      return -1;
+    }
     this->AddCMakePaths();
   }
 

+ 1 - 0
Source/cmake.h

@@ -703,6 +703,7 @@ private:
   FileExtensions HipFileExtensions;
   bool ClearBuildSystem = false;
   bool DebugTryCompile = false;
+  bool FreshCache = false;
   bool RegenerateDuringBuild = false;
   std::unique_ptr<cmFileTimeCache> FileTimeCache;
   std::string GraphVizFile;

+ 2 - 0
Source/cmakemain.cxx

@@ -73,6 +73,8 @@ const char* cmDocumentationOptions[][2] = {
   { "--list-presets", "List available presets." },
   { "-E", "CMake command mode." },
   { "-L[A][H]", "List non-advanced cached variables." },
+  { "--fresh",
+    "Configure a fresh build tree, removing any existing cache file." },
   { "--build <dir>", "Build a CMake-generated project binary tree." },
   { "--install <dir>", "Install a CMake-generated project binary tree." },
   { "--open <dir>", "Open generated project in the associated application." },

+ 4 - 0
Tests/RunCMake/CommandLine/Fresh-stdout.txt

@@ -0,0 +1,4 @@
+-- CMAKE_SOURCE_DIR='[^']*/Tests/RunCMake/CommandLine'
+-- CMAKE_BINARY_DIR='[^']*/Tests/RunCMake/CommandLine/Fresh-build'
+-- OLD CACHED_VAR_1=''
+-- NEW CACHED_VAR_1='CACHED-VALUE-1'

+ 18 - 0
Tests/RunCMake/CommandLine/Fresh.cmake

@@ -0,0 +1,18 @@
+message(STATUS "CMAKE_SOURCE_DIR='${CMAKE_SOURCE_DIR}'")
+message(STATUS "CMAKE_BINARY_DIR='${CMAKE_BINARY_DIR}'")
+message(STATUS "OLD CACHED_VAR_1='${CACHED_VAR_1}'")
+set(CACHED_VAR_1 "CACHED-VALUE-1" CACHE STRING "")
+message(STATUS "NEW CACHED_VAR_1='${CACHED_VAR_1}'")
+set(kept "${CMAKE_BINARY_DIR}/kept")
+set(removed "${CMAKE_BINARY_DIR}/CMakeFiles/removed")
+if(FIRST)
+  file(WRITE "${kept}" "")
+  file(WRITE "${removed}" "")
+else()
+  if(NOT EXISTS "${kept}")
+    message(FATAL_ERROR "File was not kept:\n ${kept}")
+  endif()
+  if(EXISTS "${removed}")
+    message(FATAL_ERROR "File was not removed:\n ${removed}")
+  endif()
+endif()

+ 3 - 2
Tests/RunCMake/CommandLine/P_arbitrary_args-stdout.txt

@@ -1,8 +1,9 @@
-^-- CMAKE_ARGC='7'
+^-- CMAKE_ARGC='8'
 -- CMAKE_ARGV1='-P'
 -- CMAKE_ARGV2='[^']*/Tests/RunCMake/CommandLine/P_arbitrary_args.cmake'
 -- CMAKE_ARGV3='--'
 -- CMAKE_ARGV4='-DFOO'
 -- CMAKE_ARGV5='-S'
 -- CMAKE_ARGV6='-B'
--- CMAKE_ARGV7=''$
+-- CMAKE_ARGV7='--fresh'
+-- CMAKE_ARGV8=''$

+ 1 - 0
Tests/RunCMake/CommandLine/P_arbitrary_args.cmake

@@ -6,3 +6,4 @@ message(STATUS "CMAKE_ARGV4='${CMAKE_ARGV4}'")
 message(STATUS "CMAKE_ARGV5='${CMAKE_ARGV5}'")
 message(STATUS "CMAKE_ARGV6='${CMAKE_ARGV6}'")
 message(STATUS "CMAKE_ARGV7='${CMAKE_ARGV7}'")
+message(STATUS "CMAKE_ARGV8='${CMAKE_ARGV8}'")

+ 1 - 0
Tests/RunCMake/CommandLine/P_fresh-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLine/P_fresh-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: --fresh allowed only when configuring a project$

+ 1 - 0
Tests/RunCMake/CommandLine/P_fresh.cmake

@@ -0,0 +1 @@
+message(FATAL_ERROR "This code should not be reached.")

+ 18 - 1
Tests/RunCMake/CommandLine/RunCMakeTest.cmake

@@ -52,7 +52,8 @@ run_cmake_command(G_no-arg ${CMAKE_COMMAND} -B DummyBuildDir -G)
 run_cmake_command(G_bad-arg ${CMAKE_COMMAND} -B DummyBuildDir -G NoSuchGenerator)
 run_cmake_command(P_no-arg ${CMAKE_COMMAND} -P)
 run_cmake_command(P_no-file ${CMAKE_COMMAND} -P nosuchscriptfile.cmake)
-run_cmake_command(P_arbitrary_args ${CMAKE_COMMAND} -P "${RunCMake_SOURCE_DIR}/P_arbitrary_args.cmake" -- -DFOO -S -B)
+run_cmake_command(P_arbitrary_args ${CMAKE_COMMAND} -P "${RunCMake_SOURCE_DIR}/P_arbitrary_args.cmake" -- -DFOO -S -B --fresh)
+run_cmake_command(P_fresh ${CMAKE_COMMAND} -P "${RunCMake_SOURCE_DIR}/P_fresh.cmake" --fresh)
 
 run_cmake_command(build-no-dir
   ${CMAKE_COMMAND} --build)
@@ -212,6 +213,22 @@ message(STATUS "CMAKE_BINARY_DIR='${CMAKE_BINARY_DIR}'")
 endfunction()
 run_ExplicitDirs()
 
+function(run_Fresh)
+  set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/Fresh-build")
+
+  set(RunCMake_TEST_VARIANT_DESCRIPTION "-empty")
+  run_cmake_with_options(Fresh --fresh -DFIRST=ON)
+  set(RunCMake_TEST_NO_CLEAN 1)
+
+  set(RunCMake_TEST_VARIANT_DESCRIPTION "-reconfig")
+  run_cmake_with_options(Fresh --fresh)
+
+  set(RunCMake_TEST_VARIANT_DESCRIPTION "-src-from-cache")
+  set(RunCMake_TEST_NO_SOURCE_DIR 1)
+  run_cmake_with_options(Fresh --fresh "${RunCMake_TEST_BINARY_DIR}")
+endfunction()
+run_Fresh()
+
 function(run_Toolchain)
   set(RunCMake_TEST_NO_SOURCE_DIR 1)
   set(source_dir ${RunCMake_SOURCE_DIR}/Toolchain)