summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/cmMakefile.cxx51
-rw-r--r--Source/cmMakefile.h5
-rw-r--r--Source/cmOptionCommand.cxx1
-rw-r--r--Source/cmPolicies.cxx31
-rw-r--r--Source/cmPolicies.h1
-rw-r--r--Source/cmSetCommand.cxx1
-rw-r--r--Source/cmSetCommand.h6
7 files changed, 94 insertions, 2 deletions
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 6732eec..8233fef 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1662,6 +1662,57 @@ void cmMakefile::AddDefinition(const char* name, const char* value)
#endif
}
+//----------------------------------------------------------------------------
+void cmMakefile::UseCacheDefinition(cmCacheManager::CacheIterator const& it)
+{
+ // Check for a local definition that might hide the cache value.
+ const char* name = it.GetName();
+ const char* def = this->Internal->VarStack.top().Get(name);
+ if(!def)
+ {
+ return;
+ }
+
+ // If the visible value will change then check policy CMP0015.
+ const char* cache = it.GetValue();
+ if(strcmp(def, cache) != 0)
+ {
+ cmOStringStream e;
+ switch (this->GetPolicyStatus(cmPolicies::CMP0015))
+ {
+ case cmPolicies::WARN:
+ e << "Local variable \"" << name << "\" is set to\n"
+ << " " << def << "\n"
+ << "but the CACHE entry of the same name is set to\n"
+ << " " << cache << "\n"
+ << "The local variable is hiding the cache value."
+ << "\n"
+ << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0015);
+ this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ case cmPolicies::OLD:
+ // OLD behavior is to leave local definition.
+ return;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ e << "Local variable \"" << name << "\" is set to\n"
+ << " " << def << "\n"
+ << "but the CACHE entry of the same name is set to\n"
+ << " " << cache << "\n"
+ << "This command is removing the local variable to expose "
+ << "the cache value."
+ << "\n"
+ << this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0015);
+ this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ case cmPolicies::NEW:
+ // NEW behavior is to remove local definition (done below).
+ break;
+ }
+ }
+
+ // Remove the local definition to make the cache value visible.
+ this->RemoveDefinition(name);
+}
+
void cmMakefile::AddCacheDefinition(const char* name, const char* value,
const char* doc,
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 6c3d218..a3a16b6 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -291,6 +291,11 @@ public:
bool force = false);
/**
+ * Update the variable scope to make the cache definition visible.
+ */
+ void UseCacheDefinition(cmCacheManager::CacheIterator const& it);
+
+ /**
* Add bool variable definition to the build.
*/
void AddDefinition(const char* name, bool);
diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx
index 8f2bd66..5bd66a5 100644
--- a/Source/cmOptionCommand.cxx
+++ b/Source/cmOptionCommand.cxx
@@ -58,6 +58,7 @@ bool cmOptionCommand
if ( it.GetType() != cmCacheManager::UNINITIALIZED )
{
it.SetProperty("HELPSTRING", args[1].c_str());
+ this->Makefile->UseCacheDefinition(it);
return true;
}
if ( it.GetValue() )
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 576ccd7..95bf972 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -399,6 +399,37 @@ cmPolicies::cmPolicies()
"The OLD behavior for this policy is to silently ignore the problem. "
"The NEW behavior for this policy is to report an error.",
2,7,20090902, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0015, "CMP0015",
+ "The set() CACHE mode and option() command make the cache value visible.",
+ "In CMake 2.6 and below the CACHE mode of the set() command and the "
+ "option() command did not expose the value from the named cache entry "
+ "if it was already set both in the cache and as a local variable. "
+ "This led to subtle differences between first and later configurations "
+ "because a conflicting local variable would be overridden only when the "
+ "cache value was first created. "
+ "For example, the code\n"
+ " set(x 1)\n"
+ " set(before ${x})\n"
+ " set(x 2 CACHE STRING \"X\")\n"
+ " set(after ${x})\n"
+ " message(STATUS \"${before},${after}\")\n"
+ "would print \"1,2\" on the first run and \"1,1\" on future runs."
+ "\n"
+ "CMake 2.8.0 and above prefer to expose the cache value in all cases by "
+ "removing the local variable definition, but this changes behavior in "
+ "subtle cases when the local variable has a different value than that "
+ "exposed from the cache. "
+ "The example above will always print \"1,2\"."
+ "\n"
+ "This policy determines whether the commands should always expose the "
+ "cache value. "
+ "The OLD behavior for this policy is to leave conflicting local "
+ "variable values untouched and hide the true cache value. "
+ "The NEW behavior for this policy is to always expose the cache value.",
+ 2,7,20090910, cmPolicies::WARN);
+
}
cmPolicies::~cmPolicies()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 49dec3b..ecb9d67 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -55,6 +55,7 @@ public:
CMP0012, // Strong handling of boolean constants
CMP0013, // Duplicate binary directories not allowed
CMP0014, // Input directories must have CMakeLists.txt
+ CMP0015, // set(CACHE) and option() make CACHE value visible
// Always the last entry. Useful mostly to avoid adding a comma
// the last policy when adding a new one.
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index b9b2b7c..e2714b6 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -160,6 +160,7 @@ bool cmSetCommand
// or the makefile
if(cache && type != cmCacheManager::INTERNAL && !force)
{
+ this->Makefile->UseCacheDefinition(it);
return true;
}
}
diff --git a/Source/cmSetCommand.h b/Source/cmSetCommand.h
index c2b65c4..1d2441a 100644
--- a/Source/cmSetCommand.h
+++ b/Source/cmSetCommand.h
@@ -69,8 +69,10 @@ public:
" set(<variable> <value>\n"
" [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE])\n"
"Within CMake sets <variable> to the value <value>. <value> is expanded"
- " before <variable> is set to it. If CACHE is present, then the "
- "<variable> is put in the cache. <type> and <docstring> are then "
+ " before <variable> is set to it. If CACHE is present and <variable> "
+ "is not yet in the cache, then <variable> is put in the cache. If it is "
+ "already in the cache, <variable> is assigned the value stored in the "
+ "cache. If CACHE is present, also <type> and <docstring> are "
"required. <type> is used by the CMake GUI to choose a widget with "
"which the user sets a value. The value for <type> may be one of\n"
" FILEPATH = File chooser dialog.\n"