cmake: Add -W options to control deprecation warnings and errors

Refactor the -Wdev and -Wno-dev to use a generic -W parser that follows
the GCC pattern.  Include support for setting CMAKE_ERROR_DEPRECATED and
CMAKE_WARN_DEPRECATED via the deprecated warning.  Add -Werror=dev and
-Wno-error=dev options so that dev warning options are in line with
deprecated warning options.  Use a new CMAKE_SUPPRESS_DEVELOPER_ERRORS
internal cache entry to store the above new dev options persistently.
Add tests for new options and updated cmake documentation and release
notes to list new options.
This commit is contained in:
Michael Scott 2015-07-28 00:07:03 +01:00 committed by Brad King
parent 98d6e9ec2d
commit c96fe0b40d
25 changed files with 374 additions and 41 deletions

View File

@ -77,10 +77,49 @@
Suppress developer warnings. Suppress developer warnings.
Suppress warnings that are meant for the author of the Suppress warnings that are meant for the author of the
CMakeLists.txt files. CMakeLists.txt files. By default this will also turn off
deprecation warnings.
``-Wdev`` ``-Wdev``
Enable developer warnings. Enable developer warnings.
Enable warnings that are meant for the author of the CMakeLists.txt Enable warnings that are meant for the author of the CMakeLists.txt
files. files. By default this will also turn on deprecation warnings.
``-Werror=dev``
Make developer warnings errors.
Make warnings that are meant for the author of the CMakeLists.txt
files errors. By default this will also turn on treatment of
deprecation warnings as errors.
``-Wno-error=dev``
Make developer warnings not errors.
Make warnings that are meant for the author of the CMakeLists.txt
files not errors. By default this will also turn off treatment of
deprecation warnings as errors.
``-Wdeprecated``
Enable deprecated macro and function warnings.
Enable warnings for usage of deprecated macros and functions, that
are meant for the author of the CMakeLists.txt files.
``-Wno-deprecated``
Suppress deprecated macro and function warnings.
Suppress warnings for usage of deprecated macros and functions, that
are meant for the author of the CMakeLists.txt files.
``-Werror=deprecated``
Make deprecated macro and function warnings errors.
Make warnings for usage of deprecated macros and functions, that
are meant for the author of the CMakeLists.txt files, errors.
``-Wno-error=deprecated``
Make deprecated macro and function warnings not errors.
Make warnings for usage of deprecated macros and functions, that
are meant for the author of the CMakeLists.txt files, not errors.

View File

@ -0,0 +1,13 @@
cmake-W-options
---------------
* The :variable:`CMAKE_ERROR_DEPRECATED` variable can now be set using the
``-Werror=deprecated`` and ``-Wno-error=deprecated`` :manual:`cmake(1)`
options.
* The :variable:`CMAKE_WARN_DEPRECATED` variable can now be set using the
``-Wdeprecated`` and ``-Wno-deprecated`` :manual:`cmake(1)` options.
* :manual:`cmake(1)` gained options ``-Werror=dev`` and ``-Wno-error=dev``
to control whether developer warnings intended for project authors
are treated as errors.

View File

@ -6,3 +6,7 @@ Whether to issue deprecation errors for macros and functions.
If TRUE, this can be used by macros and functions to issue fatal If TRUE, this can be used by macros and functions to issue fatal
errors when deprecated macros or functions are used. This variable is errors when deprecated macros or functions are used. This variable is
FALSE by default. FALSE by default.
These errors can be enabled with the ``-Werror=deprecated`` option, or
disabled with the ``-Wno-error=deprecated`` option, when running
:manual:`cmake(1)`.

View File

@ -5,3 +5,7 @@ Whether to issue deprecation warnings for macros and functions.
If TRUE, this can be used by macros and functions to issue deprecation If TRUE, this can be used by macros and functions to issue deprecation
warnings. This variable is FALSE by default. warnings. This variable is FALSE by default.
These warnings can be enabled with the ``-Wdeprecated`` option, or
disabled with the ``-Wno-deprecated`` option, when running
:manual:`cmake(1)`.

View File

@ -42,8 +42,20 @@ bool cmMessageCommand
++i; ++i;
} }
else if (*i == "AUTHOR_WARNING") else if (*i == "AUTHOR_WARNING")
{
if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS"))
{
fatal = true;
type = cmake::AUTHOR_ERROR;
}
else if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"))
{ {
type = cmake::AUTHOR_WARNING; type = cmake::AUTHOR_WARNING;
}
else
{
return true;
}
++i; ++i;
} }
else if (*i == "STATUS") else if (*i == "STATUS")

View File

@ -126,8 +126,6 @@ cmake::cmake()
this->WarnUnused = false; this->WarnUnused = false;
this->WarnUnusedCli = true; this->WarnUnusedCli = true;
this->CheckSystemVars = false; this->CheckSystemVars = false;
this->SuppressDevWarnings = false;
this->DoSuppressDevWarnings = false;
this->DebugOutput = false; this->DebugOutput = false;
this->DebugTryCompile = false; this->DebugTryCompile = false;
this->ClearBuildSystem = false; this->ClearBuildSystem = false;
@ -252,15 +250,70 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
return false; return false;
} }
} }
else if(arg.find("-Wno-dev",0) == 0) else if(cmHasLiteralPrefix(arg, "-W"))
{ {
this->SuppressDevWarnings = true; std::string entry = arg.substr(2);
this->DoSuppressDevWarnings = true; if (entry.empty())
{
++i;
if (i < args.size())
{
entry = args[i];
} }
else if(arg.find("-Wdev",0) == 0) else
{ {
this->SuppressDevWarnings = false; cmSystemTools::Error(
this->DoSuppressDevWarnings = true; "-W must be followed with [no-][error=]<name>.");
return false;
}
}
std::string name;
bool foundNo = false;
bool foundError = false;
unsigned int nameStartPosition = 0;
if (entry.find("no-", nameStartPosition) == 0)
{
foundNo = true;
nameStartPosition += 3;
}
if (entry.find("error=", nameStartPosition) == 0)
{
foundError = true;
nameStartPosition += 6;
}
name = entry.substr(nameStartPosition);
if (name.empty())
{
cmSystemTools::Error("No warning name provided.");
return false;
}
if (!foundNo && !foundError)
{
// -W<name>
this->WarningLevels[name] = std::max(this->WarningLevels[name],
WARNING_LEVEL);
}
else if (foundNo && !foundError)
{
// -Wno<name>
this->WarningLevels[name] = IGNORE_LEVEL;
}
else if (!foundNo && foundError)
{
// -Werror=<name>
this->WarningLevels[name] = ERROR_LEVEL;
}
else
{
// -Wno-error=<name>
this->WarningLevels[name] = std::min(this->WarningLevels[name],
WARNING_LEVEL);
}
} }
else if(arg.find("-U",0) == 0) else if(arg.find("-U",0) == 0)
{ {
@ -589,11 +642,7 @@ void cmake::SetArgs(const std::vector<std::string>& args,
// skip for now // skip for now
i++; i++;
} }
else if(arg.find("-Wno-dev",0) == 0) else if(arg.find("-W",0) == 0)
{
// skip for now
}
else if(arg.find("-Wdev",0) == 0)
{ {
// skip for now // skip for now
} }
@ -1180,25 +1229,121 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
int cmake::Configure() int cmake::Configure()
{ {
if(this->DoSuppressDevWarnings) WarningLevel warningLevel;
if (this->WarningLevels.count("deprecated") == 1)
{ {
if(this->SuppressDevWarnings) warningLevel = this->WarningLevels["deprecated"];
if (warningLevel == IGNORE_LEVEL)
{
this->CacheManager->
AddCacheEntry("CMAKE_WARN_DEPRECATED", "FALSE",
"Whether to issue deprecation warnings for"
" macros and functions.",
cmState::BOOL);
this->CacheManager->
AddCacheEntry("CMAKE_ERROR_DEPRECATED", "FALSE",
"Whether to issue deprecation errors for macros"
" and functions.",
cmState::BOOL);
}
if (warningLevel == WARNING_LEVEL)
{
this->CacheManager->
AddCacheEntry("CMAKE_WARN_DEPRECATED", "TRUE",
"Whether to issue deprecation warnings for"
" macros and functions.",
cmState::BOOL);
}
else if (warningLevel == ERROR_LEVEL)
{
this->CacheManager->
AddCacheEntry("CMAKE_ERROR_DEPRECATED", "TRUE",
"Whether to issue deprecation errors for macros"
" and functions.",
cmState::BOOL);
}
}
if (this->WarningLevels.count("dev") == 1)
{
bool setDeprecatedVariables = false;
const char* cachedWarnDeprecated =
this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
const char* cachedErrorDeprecated =
this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
// don't overwrite deprecated warning setting from a previous invocation
if (!cachedWarnDeprecated && !cachedErrorDeprecated)
{
setDeprecatedVariables = true;
}
warningLevel = this->WarningLevels["dev"];
if (warningLevel == IGNORE_LEVEL)
{ {
this->CacheManager-> this->CacheManager->
AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE", AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE",
"Suppress Warnings that are meant for" "Suppress Warnings that are meant for"
" the author of the CMakeLists.txt files.", " the author of the CMakeLists.txt files.",
cmState::INTERNAL); cmState::INTERNAL);
this->CacheManager->
AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", "TRUE",
"Suppress errors that are meant for"
" the author of the CMakeLists.txt files.",
cmState::INTERNAL);
if (setDeprecatedVariables)
{
this->CacheManager->
AddCacheEntry("CMAKE_WARN_DEPRECATED", "FALSE",
"Whether to issue deprecation warnings for"
" macros and functions.",
cmState::BOOL);
this->CacheManager->
AddCacheEntry("CMAKE_ERROR_DEPRECATED", "FALSE",
"Whether to issue deprecation errors for macros"
" and functions.",
cmState::BOOL);
} }
else }
else if (warningLevel == WARNING_LEVEL)
{ {
this->CacheManager-> this->CacheManager->
AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE", AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE",
"Suppress Warnings that are meant for" "Suppress Warnings that are meant for"
" the author of the CMakeLists.txt files.", " the author of the CMakeLists.txt files.",
cmState::INTERNAL); cmState::INTERNAL);
if (setDeprecatedVariables)
{
this->CacheManager->
AddCacheEntry("CMAKE_WARN_DEPRECATED", "TRUE",
"Whether to issue deprecation warnings for"
" macros and functions.",
cmState::BOOL);
} }
} }
else if (warningLevel == ERROR_LEVEL)
{
this->CacheManager->
AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", "FALSE",
"Suppress errors that are meant for"
" the author of the CMakeLists.txt files.",
cmState::INTERNAL);
if (setDeprecatedVariables)
{
this->CacheManager->
AddCacheEntry("CMAKE_ERROR_DEPRECATED", "TRUE",
"Whether to issue deprecation errors for macros"
" and functions.",
cmState::BOOL);
}
}
}
int ret = this->ActualConfigure(); int ret = this->ActualConfigure();
const char* delCacheVars = this->State const char* delCacheVars = this->State
->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_"); ->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
@ -1529,6 +1674,18 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
{ {
this->AddCMakePaths(); this->AddCMakePaths();
} }
// don't turn dev warnings into errors by default, if no value has been
// specified for the flag, enable it
if (!this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS"))
{
this->CacheManager->
AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", "TRUE",
"Suppress errors that are meant for"
" the author of the CMakeLists.txt files.",
cmState::INTERNAL);
}
// Add any cache args // Add any cache args
if ( !this->SetCacheArgs(args) ) if ( !this->SetCacheArgs(args) )
{ {
@ -2427,20 +2584,17 @@ bool cmake::PrintMessagePreamble(cmake::MessageType t, std::ostream& msg)
{ {
msg << "CMake Deprecation Warning"; msg << "CMake Deprecation Warning";
} }
else if (t == cmake::AUTHOR_WARNING)
{
msg << "CMake Warning (dev)";
}
else if (t == cmake::AUTHOR_ERROR)
{
msg << "CMake Error (dev)";
}
else else
{ {
msg << "CMake Warning"; msg << "CMake Warning";
if(t == cmake::AUTHOR_WARNING)
{
// Allow suppression of these warnings.
const char* suppress = this->State->GetCacheEntryValue(
"CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
if(suppress && cmSystemTools::IsOn(suppress))
{
return false;
}
msg << " (dev)";
}
} }
return true; return true;
} }
@ -2462,6 +2616,12 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg)
msg << msg <<
"This warning is for project developers. Use -Wno-dev to suppress it."; "This warning is for project developers. Use -Wno-dev to suppress it.";
} }
else if (t == cmake::AUTHOR_ERROR)
{
msg <<
"This error is for project developers. Use -Wno-error=dev to suppress "
"it.";
}
// Add a terminating blank line. // Add a terminating blank line.
msg << "\n"; msg << "\n";
@ -2485,7 +2645,8 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg)
// Output the message. // Output the message.
if(t == cmake::FATAL_ERROR if(t == cmake::FATAL_ERROR
|| t == cmake::INTERNAL_ERROR || t == cmake::INTERNAL_ERROR
|| t == cmake::DEPRECATION_ERROR) || t == cmake::DEPRECATION_ERROR
|| t == cmake::AUTHOR_ERROR)
{ {
cmSystemTools::SetErrorOccured(); cmSystemTools::SetErrorOccured();
cmSystemTools::Message(msg.str().c_str(), "Error"); cmSystemTools::Message(msg.str().c_str(), "Error");
@ -2663,3 +2824,18 @@ void cmake::RunCheckForUnusedVariables()
} }
#endif #endif
} }
void cmake::SetSuppressDevWarnings(bool b)
{
// equivalent to -Wno-dev
if (b)
{
this->WarningLevels["dev"] = IGNORE_LEVEL;
}
// equivalent to -Wdev
else
{
this->WarningLevels["dev"] = std::max(this->WarningLevels["dev"],
WARNING_LEVEL);
}
}

View File

@ -60,6 +60,7 @@ class cmake
public: public:
enum MessageType enum MessageType
{ AUTHOR_WARNING, { AUTHOR_WARNING,
AUTHOR_ERROR,
FATAL_ERROR, FATAL_ERROR,
INTERNAL_ERROR, INTERNAL_ERROR,
MESSAGE, MESSAGE,
@ -69,6 +70,12 @@ class cmake
DEPRECATION_WARNING DEPRECATION_WARNING
}; };
enum WarningLevel
{
IGNORE_LEVEL,
WARNING_LEVEL,
ERROR_LEVEL
};
/** \brief Describes the working modes of cmake */ /** \brief Describes the working modes of cmake */
enum WorkingMode enum WorkingMode
@ -272,6 +279,7 @@ class cmake
void SetTrace(bool b) { this->Trace = b;} void SetTrace(bool b) { this->Trace = b;}
bool GetTraceExpand() { return this->TraceExpand;} bool GetTraceExpand() { return this->TraceExpand;}
void SetTraceExpand(bool b) { this->TraceExpand = b;} void SetTraceExpand(bool b) { this->TraceExpand = b;}
void SetSuppressDevWarnings(bool b);
bool GetWarnUninitialized() { return this->WarnUninitialized;} bool GetWarnUninitialized() { return this->WarnUninitialized;}
void SetWarnUninitialized(bool b) { this->WarnUninitialized = b;} void SetWarnUninitialized(bool b) { this->WarnUninitialized = b;}
bool GetWarnUnused() { return this->WarnUnused;} bool GetWarnUnused() { return this->WarnUnused;}
@ -292,12 +300,6 @@ class cmake
std::string const& GetCMakeEditCommand() const std::string const& GetCMakeEditCommand() const
{ return this->CMakeEditCommand; } { return this->CMakeEditCommand; }
void SetSuppressDevWarnings(bool v)
{
this->SuppressDevWarnings = v;
this->DoSuppressDevWarnings = true;
}
/** Display a message to the user. */ /** Display a message to the user. */
void IssueMessage(cmake::MessageType t, std::string const& text, void IssueMessage(cmake::MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace = cmListFileBacktrace()); cmListFileBacktrace const& backtrace = cmListFileBacktrace());
@ -341,8 +343,7 @@ protected:
cmPolicies *Policies; cmPolicies *Policies;
cmGlobalGenerator *GlobalGenerator; cmGlobalGenerator *GlobalGenerator;
cmCacheManager *CacheManager; cmCacheManager *CacheManager;
bool SuppressDevWarnings; std::map<std::string, WarningLevel> WarningLevels;
bool DoSuppressDevWarnings;
std::string GeneratorPlatform; std::string GeneratorPlatform;
std::string GeneratorToolset; std::string GeneratorToolset;
@ -418,7 +419,15 @@ private:
{"-T <toolset-name>", "Specify toolset name if supported by generator."}, \ {"-T <toolset-name>", "Specify toolset name if supported by generator."}, \
{"-A <platform-name>", "Specify platform name if supported by generator."}, \ {"-A <platform-name>", "Specify platform name if supported by generator."}, \
{"-Wno-dev", "Suppress developer warnings."},\ {"-Wno-dev", "Suppress developer warnings."},\
{"-Wdev", "Enable developer warnings."} {"-Wdev", "Enable developer warnings."},\
{"-Werror=dev", "Make developer warnings errors."},\
{"-Wno-error=dev", "Make developer warnings not errors."},\
{"-Wdeprecated", "Enable deprecated macro and function warnings."},\
{"-Wno-deprecated", "Suppress deprecated macro and function warnings."},\
{"-Werror=deprecated", "Make deprecated macro and function warnings " \
"errors."},\
{"-Wno-error=deprecated", "Make deprecated macro and function warnings " \
"not errors."}
#define FOR_EACH_C_FEATURE(F) \ #define FOR_EACH_C_FEATURE(F) \
F(c_function_prototypes) \ F(c_function_prototypes) \

View File

@ -132,6 +132,52 @@ set(RunCMake_TEST_OPTIONS -Wno-dev -Wdev)
run_cmake(Wdev) run_cmake(Wdev)
unset(RunCMake_TEST_OPTIONS) unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS -Werror=dev)
run_cmake(Werror_dev)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS -Wno-error=dev)
run_cmake(Wno-error_deprecated)
unset(RunCMake_TEST_OPTIONS)
# -Wdev should not override deprecated options if specified
set(RunCMake_TEST_OPTIONS -Wdev -Wno-deprecated)
run_cmake(Wno-deprecated)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS -Wno-deprecated -Wdev)
run_cmake(Wno-deprecated)
unset(RunCMake_TEST_OPTIONS)
# -Wdev should enable deprecated warnings as well
set(RunCMake_TEST_OPTIONS -Wdev)
run_cmake(Wdeprecated)
unset(RunCMake_TEST_OPTIONS)
# -Werror=dev should enable deprecated errors as well
set(RunCMake_TEST_OPTIONS -Werror=dev)
run_cmake(Werror_deprecated)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS -Wdeprecated)
run_cmake(Wdeprecated)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS -Wno-deprecated)
run_cmake(Wno-deprecated)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS -Werror=deprecated)
run_cmake(Werror_deprecated)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS -Wno-error=deprecated)
run_cmake(Wno-error_deprecated)
unset(RunCMake_TEST_OPTIONS)
run_cmake_command(W_bad-arg1 ${CMAKE_COMMAND} -W)
run_cmake_command(W_bad-arg2 ${CMAKE_COMMAND} -Wno-)
run_cmake_command(W_bad-arg3 ${CMAKE_COMMAND} -Werror=)
set(RunCMake_TEST_OPTIONS --debug-output) set(RunCMake_TEST_OPTIONS --debug-output)
run_cmake(debug-output) run_cmake(debug-output)
unset(RunCMake_TEST_OPTIONS) unset(RunCMake_TEST_OPTIONS)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
CMake Error: -W must be followed with \[no-\]\[error=\]<name>.
CMake Error: Problem processing arguments. Aborting.

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
CMake Error: No warning name provided.
CMake Error: Problem processing arguments. Aborting.

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
CMake Error: No warning name provided.
CMake Error: Problem processing arguments. Aborting.

View File

@ -0,0 +1,4 @@
^CMake Deprecation Warning at Wdeprecated.cmake:1 \(message\):
Some deprecated warning
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1 @@
message(DEPRECATION "Some deprecated warning")

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
^CMake Deprecation Error at Werror_deprecated.cmake:1 \(message\):
Some deprecated warning
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1 @@
message(DEPRECATION "Some deprecated warning")

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,5 @@
^CMake Error \(dev\) at Werror_dev.cmake:1 \(message\):
Some author warning
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
This error is for project developers. Use -Wno-error=dev to suppress it.$

View File

@ -0,0 +1 @@
message(AUTHOR_WARNING "Some author warning")

View File

@ -0,0 +1 @@
message(DEPRECATION "Some deprecated warning")

View File

@ -0,0 +1 @@
message(DEPRECATION "Some deprecated warning")

View File

@ -0,0 +1 @@
message(AUTHOR_WARNING "Some author warning")