Merge topic 'update-cps-export-version'

a2c7854e18 install: Update CPS export version

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !10116
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5b3fda6..ad06ff9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -72,6 +72,12 @@
     needs:
         - p:source-package
 
+b:version-update:
+    extends:
+        - .cmake_version_update_linux
+        - .linux_x86_64_tags
+        - .run_version_update
+
 # Documentation builds
 
 b:cmake.org-help:
diff --git a/.gitlab/ci/cmake_version_update.sh b/.gitlab/ci/cmake_version_update.sh
new file mode 100755
index 0000000..3c05dfe
--- /dev/null
+++ b/.gitlab/ci/cmake_version_update.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+set -e
+
+if test "$CI_COMMIT_REF_NAME" != "master"; then
+  echo "The version update may run only on the 'master' branch."
+  exit 1
+fi
+
+# A project-specific access token must be provided by
+# the pipeline schedule under which this job runs.
+if test -z "$CMAKE_CI_GIT_ACCESS_TOKEN"; then
+  echo "No CMAKE_CI_GIT_ACCESS_TOKEN is available."
+  exit 1
+fi
+
+git config user.name "${CMAKE_CI_AUTHOR_NAME-Kitware Robot}"
+git config user.email "${CMAKE_CI_AUTHOR_EMAIL-kwrobot@kitware.com}"
+git remote add upstream "https://oauth2:$CMAKE_CI_GIT_ACCESS_TOKEN@gitlab.kitware.com/$CI_PROJECT_PATH.git"
+
+# Repeat a few times in case we lose a race.
+n=6
+for try in $(seq $n); do
+  git fetch upstream "$CI_COMMIT_REF_NAME"
+  git reset -q --hard FETCH_HEAD
+  Source/CMakeVersion.bash
+  git update-index -q --ignore-missing --refresh
+  modified=$(git diff-index --name-only HEAD -- "Source/CMakeVersion.cmake" "Copyright.txt")
+  if test -n "$modified"; then
+    echo "version changed"
+    git add -u
+    git commit -m "CMake Nightly Date Stamp"
+    if git push --push-option=ci.skip upstream "HEAD:$CI_COMMIT_REF_NAME"; then
+      exit 0
+    else
+      echo "Try #$try failed to fast-forward."
+    fi
+  else
+    echo "version unchanged"
+    exit 0
+  fi
+  sleep 30
+done
+
+# Give up after failing too many times.
+exit 1
diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml
index 6b8c2d0..cbdaa8e 100644
--- a/.gitlab/os-linux.yml
+++ b/.gitlab/os-linux.yml
@@ -549,6 +549,13 @@
 
     interruptible: true
 
+.cmake_version_update_linux:
+    stage: build
+    extends: .fedora41
+    script:
+        - .gitlab/ci/cmake_version_update.sh
+    interruptible: false # The job internally fetches and retries.
+
 .cmake_codespell_linux:
     stage: build
     extends: .fedora41
diff --git a/.gitlab/os-macos.yml b/.gitlab/os-macos.yml
index 2ad8a03..629d87e 100644
--- a/.gitlab/os-macos.yml
+++ b/.gitlab/os-macos.yml
@@ -7,7 +7,7 @@
         GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci ext/$CI_CONCURRENT_ID"
         # TODO: Factor this out so that each job selects the Xcode version to
         # use so that different versions can be tested in a single pipeline.
-        DEVELOPER_DIR: "/Applications/Xcode-16.1.app/Contents/Developer"
+        DEVELOPER_DIR: "/Applications/Xcode-16.2.app/Contents/Developer"
         # Avoid conflicting with other projects running on the same machine.
         SCCACHE_SERVER_PORT: 4227
 
@@ -142,7 +142,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-x86_64
         - shell
-        - xcode-16.1
+        - xcode-16.2
         - nonconcurrent
 
 .macos_x86_64_tags_ext:
@@ -150,7 +150,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-x86_64
         - shell
-        - xcode-16.1
+        - xcode-16.2
         - concurrent
 
 .macos_arm64_tags:
@@ -158,7 +158,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-arm64
         - shell
-        - xcode-16.1
+        - xcode-16.2
         - nonconcurrent
 
 .macos_arm64_tags_ext:
@@ -166,7 +166,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-arm64
         - shell
-        - xcode-16.1
+        - xcode-16.2
         - concurrent
 
 .macos_arm64_tags_package:
@@ -174,7 +174,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-arm64
         - shell
-        - xcode-16.1
+        - xcode-16.2
         - nonconcurrent
         - finder
 
diff --git a/.gitlab/rules.yml b/.gitlab/rules.yml
index 0402d33..c7102f9 100644
--- a/.gitlab/rules.yml
+++ b/.gitlab/rules.yml
@@ -2,7 +2,7 @@
 
 .run_manually:
     rules:
-        - if: '$CMAKE_CI_PACKAGE != null'
+        - if: '$CMAKE_CI_PACKAGE != null || $CMAKE_CI_VERSION_UPDATE != null'
           when: never
         - if: '($CMAKE_CI_NIGHTLY == "true" && $CMAKE_CI_JOB_NIGHTLY == "false")'
           when: never
@@ -25,7 +25,7 @@
 
 .run_automatically:
     rules:
-        - if: '$CMAKE_CI_PACKAGE != null'
+        - if: '$CMAKE_CI_PACKAGE != null || $CMAKE_CI_VERSION_UPDATE != null'
           when: never
         - if: '($CMAKE_CI_NIGHTLY == "true" && $CMAKE_CI_JOB_NIGHTLY == "false")'
           when: never
@@ -48,7 +48,7 @@
 
 .run_dependent:
     rules:
-        - if: '$CMAKE_CI_PACKAGE != null'
+        - if: '$CMAKE_CI_PACKAGE != null || $CMAKE_CI_VERSION_UPDATE != null'
           when: never
         - if: '($CMAKE_CI_NIGHTLY == "true" && $CMAKE_CI_JOB_NIGHTLY == "false")'
           when: never
@@ -86,6 +86,8 @@
 
 .run_cmake_org_help:
     rules:
+        - if: '$CMAKE_CI_VERSION_UPDATE != null'
+          when: never
         - if: '$CMAKE_CI_PACKAGE =~ /v[0-9]+\.[0-9]+/'
           variables:
               RSYNC_DESTINATION: "kitware@cmake.org:$CMAKE_CI_PACKAGE/"
@@ -105,3 +107,9 @@
               CMAKE_CI_VERSION_NO_GIT: "OFF"
           when: on_success
         - when: never
+
+.run_version_update:
+    rules:
+        - if: '$CMAKE_CI_VERSION_UPDATE != null'
+          when: on_success
+        - when: never
diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst
index 93713da..8ecfd36 100644
--- a/Help/command/try_compile.rst
+++ b/Help/command/try_compile.rst
@@ -92,10 +92,11 @@
 
 .. versionadded:: 3.25
 
-Try building an executable or static library from one or more source files
-(which one is determined by the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE`
-variable). Build success returns ``TRUE`` and build failure returns ``FALSE``
-in ``<compileResultVar>``.
+Try building an executable or static library from one or more source files.
+The binary type is determined by variable
+:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE`.
+Build success returns boolean ``true`` and build failure returns boolean
+``false`` in ``<compileResultVar>`` (cached unless ``NO_CACHE`` is specified).
 
 In this form, one or more source files must be provided. Additionally, one of
 ``SOURCES`` and/or ``SOURCE_FROM_*`` must precede other keywords.
@@ -211,9 +212,10 @@
 ``NO_CACHE``
   .. versionadded:: 3.25
 
-  The result will be stored in a normal variable rather than a cache entry.
+  ``<compileResultVar>`` will be stored in a normal variable rather than a
+  cache entry.
 
-  The result variable is normally cached so that a simple pattern can be used
+  ``<compileResultVar>`` is normally cached so that a simple pattern can be used
   to avoid repeating the test on subsequent executions of CMake:
 
   .. code-block:: cmake
diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst
index c466a81..f14a5c2 100644
--- a/Help/command/try_run.rst
+++ b/Help/command/try_run.rst
@@ -40,13 +40,14 @@
 .. versionadded:: 3.25
 
 Try building an executable from one or more source files.  Build success
-returns ``TRUE`` and build failure returns ``FALSE`` in ``<compileResultVar>``.
-If the build succeeds, this runs the executable and stores the exit code in
-``<runResultVar>``.  If the executable was built, but failed to run, then
-``<runResultVar>`` will be set to ``FAILED_TO_RUN``.  See command
-:command:`try_compile` for documentation of options common to both commands,
-and for information on how the test project is constructed to build the source
-file.
+returns boolean ``true`` and build failure returns boolean ``false`` in
+``<compileResultVar>`` (cached unless ``NO_CACHE`` is specified).
+If the build succeeds, this runs the executable and stores the exit code
+in ``<runResultVar>`` (cached unless ``NO_CACHE`` is specified).
+If the executable was built, but failed to run, then ``<runResultVar>``
+will be set to ``FAILED_TO_RUN``.  See command :command:`try_compile` for
+documentation of options common to both commands, and for information on
+how the test project is constructed to build the source file.
 
 One or more source files must be provided. Additionally, one of ``SOURCES``
 and/or ``SOURCE_FROM_*`` must precede other keywords.
diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt
index b8ea1ce..ebd94f2 100644
--- a/Help/manual/OPTIONS_BUILD.txt
+++ b/Help/manual/OPTIONS_BUILD.txt
@@ -119,6 +119,25 @@
  Specify the installation directory, used by the
  :variable:`CMAKE_INSTALL_PREFIX` variable. Must be an absolute path.
 
+.. option:: --project-file <project-file-name>
+
+ .. versionadded:: 3.32
+
+ Specify an alternate project file name.
+
+ This determines the top-level file processed by CMake when configuring a
+ project, and the file processed by :command:`add_subdirectory`.
+
+ By default, this is ``CMakeLists.txt``. If set to anything else,
+ ``CMakeLists.txt`` will be used as a fallback whenever the specified file
+ cannot be found within a project subdirectory.
+
+ .. note::
+
+  This feature is intended for temporary use by developers during an incremental
+  transition and not for publication of a final product. CMake will always emit
+  a warning when the project file is anything other than ``CMakeLists.txt``.
+
 .. option:: -Wno-dev
 
  Suppress developer warnings.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index b00ef4a..5e20196 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -82,6 +82,7 @@
    /variable/CMAKE_LINK_LIBRARY_SUFFIX
    /variable/CMAKE_LINK_SEARCH_END_STATIC
    /variable/CMAKE_LINK_SEARCH_START_STATIC
+   /variable/CMAKE_LIST_FILE_NAME
    /variable/CMAKE_MAJOR_VERSION
    /variable/CMAKE_MAKE_PROGRAM
    /variable/CMAKE_MATCH_COUNT
diff --git a/Help/release/dev/rename-cmakelists.rst b/Help/release/dev/rename-cmakelists.rst
new file mode 100644
index 0000000..f6e4a86
--- /dev/null
+++ b/Help/release/dev/rename-cmakelists.rst
@@ -0,0 +1,12 @@
+Option to specify alternate CMakeLists filename
+-----------------------------------------------
+
+* Adds :option:`cmake --project-file` option to specify an alternate filename
+  for CMakeLists files.  This determines the top-level file processed when CMake
+  is configured, and the file processed by :command:`add_subdirectory`. By
+  default, this is ``CMakeLists.txt``. If set to anything else,
+  ``CMakeLists.txt`` will be used as a fallback if the given file cannot be
+  found within a project subdirectory. The use of alternate project file names
+  is intended for temporary use by developers during an incremental transition
+  and not for publication of a final product. CMake will always emit a warning
+  when the project file is anything other than ``CMakeLists.txt``.
diff --git a/Help/variable/CMAKE_LIST_FILE_NAME.rst b/Help/variable/CMAKE_LIST_FILE_NAME.rst
new file mode 100644
index 0000000..dd35136
--- /dev/null
+++ b/Help/variable/CMAKE_LIST_FILE_NAME.rst
@@ -0,0 +1,23 @@
+CMAKE_LIST_FILE_NAME
+--------------------
+
+ .. versionadded:: 3.32
+
+The name of the CMake project files. This determines the top-level file
+processed when CMake is configured, and the file processed by
+:command:`add_subdirectory`.
+
+By default, this is ``CMakeLists.txt``. If set to anything else,
+``CMakeLists.txt`` will be used as a fallback whenever the specified file
+cannot be found within a project subdirectory.
+
+This variable reports the value set via the :option:`cmake --project-file`
+option. The value of this variable should never be set directly by projects or
+users.
+
+.. warning::
+
+  The use of alternate project file names is intended for temporary use by
+  developers during an incremental transition and not for publication of a final
+  product. CMake will always emit a warning when the project file is anything
+  other than ``CMakeLists.txt``.
diff --git a/Source/CMakeVersion.bash b/Source/CMakeVersion.bash
index 853b0ca..59f8ec2 100755
--- a/Source/CMakeVersion.bash
+++ b/Source/CMakeVersion.bash
@@ -1,7 +1,17 @@
 #!/usr/bin/env bash
 # Update the version component if it looks like a date or -f is given.
+version_file="${BASH_SOURCE%/*}/CMakeVersion.cmake"
 if test "x$1" = "x-f"; then shift ; n='*' ; else n='\{8\}' ; fi
 if test "$#" -gt 0; then echo 1>&2 "usage: CMakeVersion.bash [-f]"; exit 1; fi
 sed -i -e '
 s/\(^set(CMake_VERSION_PATCH\) [0-9]'"$n"'\(.*\)/\1 '"$(date +%Y%m%d)"'\2/
-' "${BASH_SOURCE%/*}/CMakeVersion.cmake"
+' "$version_file"
+# Update the copyright notice to match the version date's year.
+if version_patch_line=$(grep -E '^set\(CMake_VERSION_PATCH [0-9]{8}\)' "$version_file"); then
+  version_patch_year="${version_patch_line:24:4}"
+  if [[ "$version_patch_year" =~ ^[0-9][0-9][0-9][0-9]$ ]] ; then
+    sed -i -e '
+      s/\(^Copyright 2000-\)[0-9][0-9][0-9][0-9]\( .*\)/\1'"$version_patch_year"'\2/
+    ' "${BASH_SOURCE%/*}/../Copyright.txt"
+  fi
+fi
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 9a42ae6..bf43d21 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 31)
-set(CMake_VERSION_PATCH 20241217)
+set(CMake_VERSION_PATCH 20241219)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index 6255416..d5ec299 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -61,7 +61,9 @@
         return nullptr;
       }
 
-      const std::string cmakelists_file = source_dir + "/CMakeLists.txt";
+      const std::string cmlName = mf.GetSafeDefinition("CMAKE_LIST_FILE_NAME");
+      const std::string cmakelists_file = cmStrCat(
+        source_dir, "/", cmlName.empty() ? "CMakeLists.txt" : cmlName);
       if (!cmSystemTools::FileExists(cmakelists_file)) {
         std::ostringstream e;
         e << "CMakeLists.txt file does not exist [" << cmakelists_file << "]";
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 8745d0f..3f7f462 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1067,9 +1067,8 @@
 void cmGlobalXCodeGenerator::AddXCodeProjBuildRule(
   cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const
 {
-  std::string listfile =
-    cmStrCat(target->GetLocalGenerator()->GetCurrentSourceDirectory(),
-             "/CMakeLists.txt");
+  std::string listfile = this->GetCMakeInstance()->GetCMakeListFile(
+    target->GetLocalGenerator()->GetCurrentSourceDirectory());
   cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(
     listfile, false, cmSourceFileLocationKind::Known);
   if (!cm::contains(sources, srcCMakeLists)) {
@@ -4393,9 +4392,8 @@
 
       // Add CMakeLists.txt file for user convenience.
       {
-        std::string listfile =
-          cmStrCat(gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(),
-                   "/CMakeLists.txt");
+        std::string listfile = this->GetCMakeInstance()->GetCMakeListFile(
+          gtgt->GetLocalGenerator()->GetCurrentSourceDirectory());
         cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
           listfile, false, cmSourceFileLocationKind::Known);
         addSourceToGroup(sf->ResolveFullPath());
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index b4d5397..e809a99 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -229,8 +229,8 @@
     return nullptr;
   }
 
-  std::string makefileIn =
-    cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt");
+  std::string makefileIn = this->GetCMakeInstance()->GetCMakeListFile(
+    this->GetCurrentSourceDirectory());
   if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
     if (file->GetCustomCommand()) {
       return file;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index cfbe1fe..8450f75 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1711,8 +1711,8 @@
     : Makefile(mf)
   {
     std::string currentStart =
-      cmStrCat(this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource(),
-               "/CMakeLists.txt");
+      this->Makefile->GetCMakeInstance()->GetCMakeListFile(
+        this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource());
     this->Makefile->StateSnapshot.SetListFile(currentStart);
     this->Makefile->StateSnapshot =
       this->Makefile->StateSnapshot.GetState()->CreatePolicyScopeSnapshot(
@@ -1755,8 +1755,8 @@
 
 void cmMakefile::Configure()
 {
-  std::string currentStart = cmStrCat(
-    this->StateSnapshot.GetDirectory().GetCurrentSource(), "/CMakeLists.txt");
+  std::string currentStart = this->GetCMakeInstance()->GetCMakeListFile(
+    this->StateSnapshot.GetDirectory().GetCurrentSource());
 
   // Add the bottom of all backtraces within this directory.
   // We will never pop this scope because it should be available
@@ -1909,8 +1909,8 @@
     cmSystemTools::Message(msg);
   }
 
-  std::string const currentStartFile =
-    cmStrCat(currentStart, "/CMakeLists.txt");
+  std::string currentStartFile =
+    this->GetCMakeInstance()->GetCMakeListFile(currentStart);
   if (!cmSystemTools::FileExists(currentStartFile, true)) {
     // The file is missing.  Check policy CMP0014.
     auto e = cmStrCat("The source directory\n  ", currentStart,
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 7289740..5b4d58f 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -259,7 +259,7 @@
 
 } // namespace
 
-cmDocumentationEntry cmake::CMAKE_STANDARD_OPTIONS_TABLE[18] = {
+cmDocumentationEntry cmake::CMAKE_STANDARD_OPTIONS_TABLE[19] = {
   { "-S <path-to-source>", "Explicitly specify a source directory." },
   { "-B <path-to-build>", "Explicitly specify a build directory." },
   { "-C <initial-cache>", "Pre-load a script to populate the cache." },
@@ -271,6 +271,8 @@
   { "--toolchain <file>", "Specify toolchain file [CMAKE_TOOLCHAIN_FILE]." },
   { "--install-prefix <directory>",
     "Specify install directory [CMAKE_INSTALL_PREFIX]." },
+  { "--project-file <project-file-name>",
+    "Specify an alternate project file name." },
   { "-Wdev", "Enable developer warnings." },
   { "-Wno-dev", "Suppress developer warnings." },
   { "-Werror=dev", "Make developer warnings errors." },
@@ -930,6 +932,7 @@
   bool haveToolset = false;
   bool havePlatform = false;
   bool haveBArg = false;
+  bool haveCMLName = false;
   std::string possibleUnknownArg;
   std::string extraProvidedPath;
 #if !defined(CMAKE_BOOTSTRAP)
@@ -988,6 +991,17 @@
     return true;
   };
 
+  auto CMakeListsFileLambda = [&](std::string const& value,
+                                  cmake* state) -> bool {
+    if (haveCMLName) {
+      cmSystemTools::Error("Multiple --project-file options not allowed");
+      return false;
+    }
+    state->SetCMakeListName(value);
+    haveCMLName = true;
+    return true;
+  };
+
   std::vector<CommandArgument> arguments = {
     CommandArgument{ "", CommandArgument::Values::Zero, EmptyStringArgLambda },
     CommandArgument{ "-S", "No source directory specified for -S",
@@ -1120,6 +1134,9 @@
                        state->SetShowLogContext(true);
                        return true;
                      } },
+    CommandArgument{ "--project-file",
+                     "No filename specified for --project-file",
+                     CommandArgument::Values::One, CMakeListsFileLambda },
     CommandArgument{
       "--debug-find", CommandArgument::Values::Zero,
       [](std::string const&, cmake* state) -> bool {
@@ -1773,8 +1790,9 @@
 
 bool cmake::SetDirectoriesFromFile(const std::string& arg)
 {
-  // Check if the argument refers to a CMakeCache.txt or
-  // CMakeLists.txt file.
+  // Check if the argument refers to a CMakeCache.txt or CMakeLists.txt file.
+  // Do not check for the custom project filename CMAKE_LIST_FILE_NAME, as it
+  // cannot be determined until after reading the CMakeCache.txt
   std::string listPath;
   std::string cachePath;
   bool is_source_dir = false;
@@ -1782,7 +1800,7 @@
   if (cmSystemTools::FileIsDirectory(arg)) {
     std::string path = cmSystemTools::ToNormalizedPathOnDisk(arg);
     std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
-    std::string listFile = cmStrCat(path, "/CMakeLists.txt");
+    std::string listFile = this->GetCMakeListFile(path);
 
     is_empty_directory = true;
     if (cmSystemTools::FileExists(cacheFile)) {
@@ -2177,12 +2195,13 @@
 int cmake::DoPreConfigureChecks()
 {
   // Make sure the Source directory contains a CMakeLists.txt file.
-  std::string srcList = cmStrCat(this->GetHomeDirectory(), "/CMakeLists.txt");
+  std::string srcList =
+    cmStrCat(this->GetHomeDirectory(), "/", this->CMakeListName);
   if (!cmSystemTools::FileExists(srcList)) {
     std::ostringstream err;
     if (cmSystemTools::FileIsDirectory(this->GetHomeDirectory())) {
       err << "The source directory \"" << this->GetHomeDirectory()
-          << "\" does not appear to contain CMakeLists.txt.\n";
+          << "\" does not appear to contain " << this->CMakeListName << ".\n";
     } else if (cmSystemTools::FileExists(this->GetHomeDirectory())) {
       err << "The source directory \"" << this->GetHomeDirectory()
           << "\" is a file, not a directory.\n";
@@ -2200,7 +2219,7 @@
   if (this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY")) {
     std::string cacheStart =
       cmStrCat(*this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY"),
-               "/CMakeLists.txt");
+               "/", this->CMakeListName);
     if (!cmSystemTools::SameFile(cacheStart, srcList)) {
       std::string message =
         cmStrCat("The source \"", srcList, "\" does not match the source \"",
@@ -2375,6 +2394,33 @@
   cmSystemTools::RemoveADirectory(this->GetHomeOutputDirectory() +
                                   "/CMakeFiles/CMakeScratch");
 
+  std::string cmlNameCache =
+    this->State->GetInitializedCacheValue("CMAKE_LIST_FILE_NAME");
+  if (!cmlNameCache.empty() && !this->CMakeListName.empty() &&
+      cmlNameCache != this->CMakeListName) {
+    std::string message =
+      cmStrCat("CMakeLists filename : \"", this->CMakeListName,
+               "\"\nDoes not match the previous: \"", cmlNameCache,
+               "\"\nEither remove the CMakeCache.txt file and CMakeFiles "
+               "directory or choose a different binary directory.");
+    cmSystemTools::Error(message);
+    return -2;
+  }
+  if (this->CMakeListName.empty()) {
+    this->CMakeListName =
+      cmlNameCache.empty() ? "CMakeLists.txt" : cmlNameCache;
+  }
+  if (this->CMakeListName != "CMakeLists.txt") {
+    this->IssueMessage(
+      MessageType::WARNING,
+      "This project has been configured with a project file other than "
+      "CMakeLists.txt. This feature is intended for temporary use during "
+      "development and not for publication of a final product.");
+  }
+  this->AddCacheEntry("CMAKE_LIST_FILE_NAME", this->CMakeListName,
+                      "Name of CMakeLists files to read",
+                      cmStateEnums::INTERNAL);
+
   int res = this->DoPreConfigureChecks();
   if (res < 0) {
     return -2;
@@ -4230,6 +4276,21 @@
   return this->DebugFindPkgs.count(pkg);
 }
 
+void cmake::SetCMakeListName(const std::string& name)
+{
+  this->CMakeListName = name;
+}
+
+std::string cmake::GetCMakeListFile(const std::string& dir) const
+{
+  std::string listFile = cmStrCat(dir, '/', this->CMakeListName);
+  if (this->CMakeListName.empty() ||
+      !cmSystemTools::FileExists(listFile, true)) {
+    return cmStrCat(dir, "/CMakeLists.txt");
+  }
+  return listFile;
+}
+
 #if !defined(CMAKE_BOOTSTRAP)
 cmMakefileProfilingData& cmake::GetProfilingOutput()
 {
diff --git a/Source/cmake.h b/Source/cmake.h
index 271b914..d79629a 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -664,6 +664,9 @@
 
   bool GetRegenerateDuringBuild() const { return this->RegenerateDuringBuild; }
 
+  void SetCMakeListName(const std::string& name);
+  std::string GetCMakeListFile(const std::string& dir) const;
+
 #if !defined(CMAKE_BOOTSTRAP)
   cmMakefileProfilingData& GetProfilingOutput();
   bool IsProfilingEnabled() const;
@@ -788,6 +791,7 @@
   bool DebugTryCompile = false;
   bool FreshCache = false;
   bool RegenerateDuringBuild = false;
+  std::string CMakeListName;
   std::unique_ptr<cmFileTimeCache> FileTimeCache;
   std::string GraphVizFile;
   InstalledFilesMap InstalledFiles;
@@ -857,7 +861,7 @@
   void SetScriptModeExitCode(int code) { ScriptModeExitCode = code; }
   int GetScriptModeExitCode() const { return ScriptModeExitCode.value_or(-1); }
 
-  static cmDocumentationEntry CMAKE_STANDARD_OPTIONS_TABLE[18];
+  static cmDocumentationEntry CMAKE_STANDARD_OPTIONS_TABLE[19];
 };
 
 #define FOR_EACH_C90_FEATURE(F) F(c_function_prototypes)
diff --git a/Tests/RunCMake/CMakeListFileName/CMakeLists.txt b/Tests/RunCMake/CMakeListFileName/CMakeLists.txt
new file mode 100644
index 0000000..94e43ba
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.29)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMakeListFileName/RunCMakeTest.cmake b/Tests/RunCMake/CMakeListFileName/RunCMakeTest.cmake
new file mode 100644
index 0000000..c787900
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/RunCMakeTest.cmake
@@ -0,0 +1,15 @@
+include(RunCMake)
+
+block()
+  set(source ${RunCMake_SOURCE_DIR}/project)
+  run_cmake_command(dont-set-file ${CMAKE_COMMAND} -S ${source})
+  run_cmake_command(set-file-dne ${CMAKE_COMMAND} -S ${source} --project-file dne.cmake)
+  run_cmake_command(set-file-multi ${CMAKE_COMMAND} -S ${source} --project-file 1 --project-file 2)
+  run_cmake_command(set-file-none ${CMAKE_COMMAND} -S ${source} --project-file)
+
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/other)
+  run_cmake_command(set-file ${CMAKE_COMMAND} -S ${source} --project-file other.cmake)
+  run_cmake_command(remembers-file ${CMAKE_COMMAND} -S ${source})
+  run_cmake_command(cant-change-file ${CMAKE_COMMAND} -S ${source} --project-file another.cmake)
+endblock()
diff --git a/Tests/RunCMake/CMakeListFileName/cant-change-file-result.txt b/Tests/RunCMake/CMakeListFileName/cant-change-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/cant-change-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakeListFileName/cant-change-file-stderr.txt b/Tests/RunCMake/CMakeListFileName/cant-change-file-stderr.txt
new file mode 100644
index 0000000..25d3d61
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/cant-change-file-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error: CMakeLists filename : \"another.cmake\"
+Does not match the previous: \"other.cmake\"
+Either remove the CMakeCache.txt file and CMakeFiles directory or choose a different binary directory.
diff --git a/Tests/RunCMake/CMakeListFileName/dont-set-file-stdout.txt b/Tests/RunCMake/CMakeListFileName/dont-set-file-stdout.txt
new file mode 100644
index 0000000..787db38
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/dont-set-file-stdout.txt
@@ -0,0 +1,3 @@
+\-\- Processing: CMakeLists.txt
+\-\- Processing: subdir-1/CMakeLists.txt
+\-\- Processing: subdir-2/CMakeLists.txt
diff --git a/Tests/RunCMake/CMakeListFileName/project/CMakeLists.txt b/Tests/RunCMake/CMakeListFileName/project/CMakeLists.txt
new file mode 100644
index 0000000..8d35b34
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/project/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.31)
+project(test)
+message(STATUS "Processing: CMakeLists.txt")
+add_subdirectory(subdir-1)
+add_subdirectory(subdir-2)
diff --git a/Tests/RunCMake/CMakeListFileName/project/other.cmake b/Tests/RunCMake/CMakeListFileName/project/other.cmake
new file mode 100644
index 0000000..b9bb06e
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/project/other.cmake
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.31)
+project(test)
+message(STATUS "Processing: other.cmake")
+add_subdirectory(subdir-1)
+add_subdirectory(subdir-2)
diff --git a/Tests/RunCMake/CMakeListFileName/project/subdir-1/CMakeLists.txt b/Tests/RunCMake/CMakeListFileName/project/subdir-1/CMakeLists.txt
new file mode 100644
index 0000000..455d9e5
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/project/subdir-1/CMakeLists.txt
@@ -0,0 +1 @@
+message(STATUS "Processing: subdir-1/CMakeLists.txt")
diff --git a/Tests/RunCMake/CMakeListFileName/project/subdir-1/other.cmake b/Tests/RunCMake/CMakeListFileName/project/subdir-1/other.cmake
new file mode 100644
index 0000000..f26252b
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/project/subdir-1/other.cmake
@@ -0,0 +1 @@
+message(STATUS "Processing: subdir-1/other.cmake")
diff --git a/Tests/RunCMake/CMakeListFileName/project/subdir-2/CMakeLists.txt b/Tests/RunCMake/CMakeListFileName/project/subdir-2/CMakeLists.txt
new file mode 100644
index 0000000..3a69f44
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/project/subdir-2/CMakeLists.txt
@@ -0,0 +1 @@
+message(STATUS "Processing: subdir-2/CMakeLists.txt")
diff --git a/Tests/RunCMake/CMakeListFileName/remembers-file-stderr.txt b/Tests/RunCMake/CMakeListFileName/remembers-file-stderr.txt
new file mode 100644
index 0000000..e35c60e
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/remembers-file-stderr.txt
@@ -0,0 +1,4 @@
+CMake Warning:
+  This project has been configured with a project file other than
+  CMakeLists.txt.  This feature is intended for temporary use during
+  development and not for publication of a final product.
diff --git a/Tests/RunCMake/CMakeListFileName/remembers-file-stdout.txt b/Tests/RunCMake/CMakeListFileName/remembers-file-stdout.txt
new file mode 100644
index 0000000..c1cb088
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/remembers-file-stdout.txt
@@ -0,0 +1,3 @@
+\-\- Processing: other.cmake
+\-\- Processing: subdir-1/other.cmake
+\-\- Processing: subdir-2/CMakeLists.txt
diff --git a/Tests/RunCMake/CMakeListFileName/set-file-dne-result.txt b/Tests/RunCMake/CMakeListFileName/set-file-dne-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/set-file-dne-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakeListFileName/set-file-dne-stderr.txt b/Tests/RunCMake/CMakeListFileName/set-file-dne-stderr.txt
new file mode 100644
index 0000000..ab7c26b
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/set-file-dne-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning:
+  This project has been configured with a project file other than
+  CMakeLists.txt.  This feature is intended for temporary use during
+  development and not for publication of a final product.
+
+
+CMake Error: The source directory [^
+]* does not appear to contain dne.cmake.
+Specify --help for usage, or press the help button on the CMake GUI.
diff --git a/Tests/RunCMake/CMakeListFileName/set-file-multi-result.txt b/Tests/RunCMake/CMakeListFileName/set-file-multi-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/set-file-multi-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakeListFileName/set-file-multi-stderr.txt b/Tests/RunCMake/CMakeListFileName/set-file-multi-stderr.txt
new file mode 100644
index 0000000..9cfb84d
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/set-file-multi-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Multiple --project-file options not allowed
+CMake Error: Run 'cmake --help' for all supported options
diff --git a/Tests/RunCMake/CMakeListFileName/set-file-none-result.txt b/Tests/RunCMake/CMakeListFileName/set-file-none-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/set-file-none-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakeListFileName/set-file-none-stderr.txt b/Tests/RunCMake/CMakeListFileName/set-file-none-stderr.txt
new file mode 100644
index 0000000..ffeca30
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/set-file-none-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: No filename specified for --project-file
+CMake Error: Run 'cmake --help' for all supported options.
diff --git a/Tests/RunCMake/CMakeListFileName/set-file-stderr.txt b/Tests/RunCMake/CMakeListFileName/set-file-stderr.txt
new file mode 100644
index 0000000..e35c60e
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/set-file-stderr.txt
@@ -0,0 +1,4 @@
+CMake Warning:
+  This project has been configured with a project file other than
+  CMakeLists.txt.  This feature is intended for temporary use during
+  development and not for publication of a final product.
diff --git a/Tests/RunCMake/CMakeListFileName/set-file-stdout.txt b/Tests/RunCMake/CMakeListFileName/set-file-stdout.txt
new file mode 100644
index 0000000..c1cb088
--- /dev/null
+++ b/Tests/RunCMake/CMakeListFileName/set-file-stdout.txt
@@ -0,0 +1,3 @@
+\-\- Processing: other.cmake
+\-\- Processing: subdir-1/other.cmake
+\-\- Processing: subdir-2/CMakeLists.txt
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 092b147..92d258d 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -1258,6 +1258,8 @@
 add_RunCMake_test(VerifyHeaderSets)
 add_RunCMake_test(set_tests_properties)
 
+add_RunCMake_test(CMakeListFileName)
+
 if(CMAKE_GENERATOR MATCHES "Make|Ninja")
   add_RunCMake_test(Codegen)
   add_RunCMake_test(TransformDepfile)
diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in
index 8ff9b0e..d6df5a1 100644
--- a/Utilities/Sphinx/conf.py.in
+++ b/Utilities/Sphinx/conf.py.in
@@ -91,6 +91,7 @@
 linkcheck_ignore = [
     r'about:',
     r'https://gitlab\.kitware\.com/cmake/community/-/wikis/doc/cpack',
+    r'https://web\.archive\.org/',
     r'https://www\.intel\.com/',
     r'https://www\.tasking\.com($|/)',
 ]