mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
CMAKE_TOOLCHAIN_FILE: Improve recovery from changed compiler or toolchain file
Replace __CMAKE_DELETE_CACHE_CHANGE_VARS_ with a set of changed
variables in cmState to avoid interference from scripts and simplify
handling of changed variables.
Errors during configure step will block re-configure when the toolchain
file has changed. Downstream errors can be caused by failing in
EnableLanguage without an error, behavior introduced in 7a989ed58a
(CMAKE_TOOLCHAIN_FILE: Detect path changes and reset cache, 2026-06-24).
Errors directly related to a changed toolchain file should be fixed by
using the new one.
Trigger a fatal error when the toolchain file change is detected to
avoid wasteful configure that will be reset anyway, then re-configure
only for that specific case. Avoid re-configuring multiple times.
Fixes: #27867
This commit is contained in:
@@ -295,17 +295,8 @@ void cmGlobalGenerator::ResolveLanguageCompiler(std::string const& lang,
|
||||
}
|
||||
cmCMakePath foundPath = path;
|
||||
if (foundPath.Normal() != cachedPath.Normal()) {
|
||||
cmValue cvars = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
|
||||
"__CMAKE_DELETE_CACHE_CHANGE_VARS_");
|
||||
if (cvars) {
|
||||
changeVars += *cvars;
|
||||
changeVars += ";";
|
||||
}
|
||||
changeVars += langComp;
|
||||
changeVars += ";";
|
||||
changeVars += *cname;
|
||||
this->GetCMakeInstance()->GetState()->SetGlobalProperty(
|
||||
"__CMAKE_DELETE_CACHE_CHANGE_VARS_", changeVars);
|
||||
this->GetCMakeInstance()->GetState()->AddDeleteCacheChangeVar(langComp,
|
||||
*cname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -716,12 +707,12 @@ void cmGlobalGenerator::EnableLanguage(
|
||||
cmValue storedToolchainFile =
|
||||
mf->GetDefinition("_CMAKE_SYSTEM_TOOLCHAIN_FILE");
|
||||
if (toolchainFile && toolchainFile != storedToolchainFile) {
|
||||
mf->GetState()->AppendGlobalProperty(
|
||||
"__CMAKE_DELETE_CACHE_CHANGE_VARS_",
|
||||
"CMAKE_TOOLCHAIN_FILE;" + *toolchainFile);
|
||||
mf->GetState()->AddDeleteCacheChangeVar("CMAKE_TOOLCHAIN_FILE",
|
||||
*toolchainFile);
|
||||
for (std::string const& lang : cur_languages) {
|
||||
this->LanguagesInProgress.erase(lang);
|
||||
}
|
||||
cmSystemTools::SetFatalErrorOccurred();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
@@ -263,6 +264,22 @@ public:
|
||||
}
|
||||
bool InTopLevelIncludes() const { return this->ProcessingTopLevelIncludes; }
|
||||
|
||||
void ClearDeleteCacheChangeVars() { this->DeleteCacheChangeVars.clear(); }
|
||||
void AddDeleteCacheChangeVar(std::string var, std::string value)
|
||||
{
|
||||
this->DeleteCacheChangeVars[var] = value;
|
||||
}
|
||||
std::map<std::string, std::string> GetDeleteCacheChangeVars() const
|
||||
{
|
||||
return this->DeleteCacheChangeVars;
|
||||
}
|
||||
|
||||
void SetReconfiguring(bool reconfiguring)
|
||||
{
|
||||
this->Reconfiguring = reconfiguring;
|
||||
}
|
||||
bool IsReconfiguring() const { return this->Reconfiguring; }
|
||||
|
||||
private:
|
||||
friend class cmake;
|
||||
cmStateSnapshot Reset(cmStateSnapshot const& diagnosticState);
|
||||
@@ -342,4 +359,6 @@ private:
|
||||
TryCompile IsTryCompile = TryCompile::No;
|
||||
cm::optional<cmDependencyProvider> DependencyProvider;
|
||||
bool ProcessingTopLevelIncludes = false;
|
||||
std::map<std::string, std::string> DeleteCacheChangeVars;
|
||||
bool Reconfiguring = false;
|
||||
};
|
||||
|
||||
+21
-19
@@ -2374,11 +2374,11 @@ struct SaveCacheEntry
|
||||
cmStateEnums::CacheEntryType type;
|
||||
};
|
||||
|
||||
int cmake::HandleDeleteCacheVariables(std::string const& var)
|
||||
int cmake::HandleDeleteCacheVariables(
|
||||
std::map<std::string, std::string> const& vars)
|
||||
{
|
||||
cmList argsSplit{ var, cmList::EmptyElements::Yes };
|
||||
// erase the property to avoid infinite recursion
|
||||
this->State->SetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
|
||||
// erase the set to avoid infinite recursion
|
||||
this->State->ClearDeleteCacheChangeVars();
|
||||
if (this->GetIsInTryCompile()) {
|
||||
return 0;
|
||||
}
|
||||
@@ -2388,18 +2388,11 @@ int cmake::HandleDeleteCacheVariables(std::string const& var)
|
||||
<< "You have changed variables that require your cache to be deleted.\n"
|
||||
"Configure will be re-run and you may have to reset some variables.\n"
|
||||
"The following variables have changed:\n";
|
||||
for (auto i = argsSplit.begin(); i != argsSplit.end(); ++i) {
|
||||
for (auto const& var : vars) {
|
||||
SaveCacheEntry save;
|
||||
save.key = *i;
|
||||
warning << *i << "= ";
|
||||
i++;
|
||||
if (i != argsSplit.end()) {
|
||||
save.value = *i;
|
||||
warning << *i << '\n';
|
||||
} else {
|
||||
warning << '\n';
|
||||
i -= 1;
|
||||
}
|
||||
save.key = var.first;
|
||||
save.value = var.second;
|
||||
warning << save.key << "= " << save.value << '\n';
|
||||
cmValue existingValue = this->State->GetCacheEntryValue(save.key);
|
||||
if (existingValue) {
|
||||
save.type = this->State->GetCacheEntryType(save.key);
|
||||
@@ -2425,6 +2418,15 @@ int cmake::HandleDeleteCacheVariables(std::string const& var)
|
||||
// avoid reconfigure if there were errors
|
||||
if (!cmSystemTools::GetErrorOccurredFlag()) {
|
||||
// re-run configure
|
||||
this->State->SetReconfiguring(true);
|
||||
return this->Configure();
|
||||
}
|
||||
|
||||
// Toolchain changes trigger a fatal error, but reconfiguring with the new
|
||||
// toolchain should fix them.
|
||||
if (vars.count("CMAKE_TOOLCHAIN_FILE") && !this->State->IsReconfiguring()) {
|
||||
cmSystemTools::ResetErrorOccurredFlag();
|
||||
this->State->SetReconfiguring(true);
|
||||
return this->Configure();
|
||||
}
|
||||
return 0;
|
||||
@@ -2523,10 +2525,10 @@ int cmake::Configure()
|
||||
cmStateEnums::INTERNAL);
|
||||
|
||||
int ret = this->ActualConfigure();
|
||||
cmValue delCacheVars =
|
||||
this->State->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
|
||||
if (delCacheVars && !delCacheVars->empty()) {
|
||||
return this->HandleDeleteCacheVariables(*delCacheVars);
|
||||
std::map<std::string, std::string> delCacheVars =
|
||||
this->State->GetDeleteCacheChangeVars();
|
||||
if (!delCacheVars.empty()) {
|
||||
return this->HandleDeleteCacheVariables(delCacheVars);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
+2
-1
@@ -710,7 +710,8 @@ public:
|
||||
|
||||
protected:
|
||||
void RunCheckForUnusedVariables();
|
||||
int HandleDeleteCacheVariables(std::string const& var);
|
||||
int HandleDeleteCacheVariables(
|
||||
std::map<std::string, std::string> const& var);
|
||||
|
||||
using RegisteredGeneratorsVector =
|
||||
std::vector<std::unique_ptr<cmGlobalGeneratorFactory>>;
|
||||
|
||||
@@ -59,6 +59,16 @@ block()
|
||||
run_cmake(ToolchainFromFile-step2)
|
||||
endblock()
|
||||
|
||||
# New toolchain path comes from file but old toolchain has been deleted
|
||||
file(WRITE "${RunCMake_BINARY_DIR}/baz.cmake" "set(toolchain_var baz)\n")
|
||||
block()
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ToolchainFromFileDeleted-build)
|
||||
run_cmake(ToolchainFromFileDeleted-step1)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
set(ENV{RunCMake_TEST} "ToolchainFromFileDeleted-step2")
|
||||
run_cmake(ToolchainFromFileDeleted-step2)
|
||||
endblock()
|
||||
|
||||
# New toolchain path comes from command line
|
||||
block()
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ToolchainFromCmdline-build)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
file(WRITE
|
||||
"${RunCMake_TEST_BINARY_DIR}/toolchain.txt"
|
||||
"${RunCMake_BINARY_DIR}/baz.cmake\n"
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Toolchain file: [^
|
||||
]*/Tests/RunCMake/CompilerChange/baz\.cmake
|
||||
-- Using toolchain: baz
|
||||
@@ -0,0 +1,2 @@
|
||||
message(STATUS "Toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
message(STATUS "Using toolchain: ${toolchain_var}")
|
||||
@@ -0,0 +1,5 @@
|
||||
file(REMOVE "${RunCMake_BINARY_DIR}/baz.cmake")
|
||||
file(WRITE
|
||||
"${RunCMake_TEST_BINARY_DIR}/toolchain.txt"
|
||||
"${RunCMake_BINARY_DIR}/bar.cmake\n"
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
You have changed variables that require your cache to be deleted.
|
||||
Configure will be re-run and you may have to reset some variables.
|
||||
The following variables have changed:
|
||||
CMAKE_TOOLCHAIN_FILE= [^
|
||||
]*/Tests/RunCMake/CompilerChange/bar\.cmake
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Toolchain file: [^
|
||||
]*/Tests/RunCMake/CompilerChange/bar\.cmake
|
||||
-- Using toolchain: bar
|
||||
@@ -0,0 +1,2 @@
|
||||
message(STATUS "Toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
message(STATUS "Using toolchain: ${toolchain_var}")
|
||||
Reference in New Issue
Block a user