From 4d712cfc25175395c9b59c1d246748dc9d63d758 Mon Sep 17 00:00:00 2001 From: Martin Duffy Date: Wed, 14 Jan 2026 11:42:58 -0500 Subject: fileapi: Fix crash on cmake_file_api() call in initial cache --- Source/cmFileAPI.cxx | 3 ++- Source/cmake.cxx | 12 +++++++++++- Source/cmake.h | 1 + Tests/RunCMake/FileAPI/InitialCache-check.cmake | 8 ++++++++ Tests/RunCMake/FileAPI/InitialCache-script.cmake | 5 +++++ Tests/RunCMake/FileAPI/InitialCache.cmake | 0 Tests/RunCMake/FileAPI/RunCMakeTest.cmake | 1 + 7 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/FileAPI/InitialCache-check.cmake create mode 100644 Tests/RunCMake/FileAPI/InitialCache-script.cmake create mode 100644 Tests/RunCMake/FileAPI/InitialCache.cmake diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx index 1f15612..520e29d 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -58,7 +58,8 @@ void cmFileAPI::ReadQueries() { std::string const query_dir = cmStrCat(this->APIv1, "/query"); std::string const user_query_dir = cmStrCat(this->UserAPIv1, "/query"); - this->QueryExists = cmSystemTools::FileIsDirectory(query_dir); + this->QueryExists = + this->QueryExists || cmSystemTools::FileIsDirectory(query_dir); if (!this->UserAPIv1.empty()) { this->QueryExists = this->QueryExists || cmSystemTools::FileIsDirectory(user_query_dir); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 3fa18ce..ed37ae4 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -691,6 +691,7 @@ bool cmake::SetCacheArgs(const std::vector& args) // Resolve script path specified on command line // relative to $PWD. auto path = cmSystemTools::CollapseFullPath(value); + state->InitializeFileAPI(); state->ReadListFile(args, path); return true; } }, @@ -2549,7 +2550,7 @@ int cmake::ActualConfigure() } #if !defined(CMAKE_BOOTSTRAP) - this->FileAPI = cm::make_unique(this); + this->InitializeFileAPI(); this->FileAPI->ReadQueries(); if (!this->GetIsInTryCompile()) { @@ -2771,6 +2772,15 @@ void cmake::StopDebuggerIfNeeded(int exitCode) #endif +void cmake::InitializeFileAPI() +{ +#ifndef CMAKE_BOOTSTRAP + if (!this->FileAPI) { + this->FileAPI = cm::make_unique(this); + } +#endif +} + // handle a command line invocation int cmake::Run(const std::vector& args, bool noconfigure) { diff --git a/Source/cmake.h b/Source/cmake.h index cfe4edd..d3ba531 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -646,6 +646,7 @@ public: #if !defined(CMAKE_BOOTSTRAP) cmFileAPI* GetFileAPI() const { return this->FileAPI.get(); } #endif + void InitializeFileAPI(); cmState* GetState() const { return this->State.get(); } void SetCurrentSnapshot(cmStateSnapshot const& snapshot) diff --git a/Tests/RunCMake/FileAPI/InitialCache-check.cmake b/Tests/RunCMake/FileAPI/InitialCache-check.cmake new file mode 100644 index 0000000..3767f15 --- /dev/null +++ b/Tests/RunCMake/FileAPI/InitialCache-check.cmake @@ -0,0 +1,8 @@ +set(expect + reply + reply/codemodel-v2-[0-9a-f]+.json + .*reply/index-[0-9.T-]+.json.* +) + +# Only need to check for existence. Other tests check the reply contents. +check_api("^${expect}$") diff --git a/Tests/RunCMake/FileAPI/InitialCache-script.cmake b/Tests/RunCMake/FileAPI/InitialCache-script.cmake new file mode 100644 index 0000000..9d8505f --- /dev/null +++ b/Tests/RunCMake/FileAPI/InitialCache-script.cmake @@ -0,0 +1,5 @@ +cmake_file_api( + QUERY + API_VERSION 1 + CODEMODEL 2 +) diff --git a/Tests/RunCMake/FileAPI/InitialCache.cmake b/Tests/RunCMake/FileAPI/InitialCache.cmake new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake index 81926af..652265c 100644 --- a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake +++ b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake @@ -52,6 +52,7 @@ run_cmake(ClientStateless) run_cmake(MixedStateless) run_cmake(DuplicateStateless) run_cmake(ClientStateful) +run_cmake_with_options(InitialCache -C ${RunCMake_SOURCE_DIR}/InitialCache-script.cmake) run_cmake(ProjectQueryGood) run_cmake(ProjectQueryBad) -- cgit v0.12