Merge topic 'dev/strict-mode'
dd2f814
Merge branch 'dev/add_test-working-directory' into dev/strict-mode949d32c
Unwatch manual variables upon removal in cmake-gui3939032
Unwatch manual variables upon removal in ccmake8354413
Add method to unwatch a manual variable8ed3c85
Give a better message for unused variables729db48
Fix ArgumentExpansion test expected results89c2544
Checking for a definition is a usage5625dee
Don't output to stderr in the GUIad25a96
Merge branch 'ImprovedDotSupport2' into dev/strict-modec128abe
Merge branch 'AddCMAKE_CURRENT_LIST_DIR' into dev/strict-mode9bcaff0
Merge branch 'cmake-guiRememberAdvancedCheckbox' into dev/strict-mode544d0c3
Fix expected output for WarnUninitialized test4e3bea4
Update expected messages to new format8e8c9e4
Don't check at destruction for usage668e005
Use cmake::IssueMessage for warnings88cd4c1
Use 'CMake Warning' versus 'warning' for CDash3c3b98d
Initialize the class before setting warn flagscf8b15a
Ignore files under the CMakeFiles directoryfd50f06
Don't check for unused vars at configure time447a04c
Don't warn during configure when doing everythingb97ee21
Check for unused variables at the end of generatec18c977
When checking for variables, specify a reason3f1121f
Use a long int since Line is a long as well2507f93
Change the failure case string to 'Unexpected'fe390a2
Add 'ArgumentExpansion' test8dbb209
Wrong boolean value for CLI warningsd4ee998
Hard-code the --no-warn-unused-cli flaga267b99
Fix line lengths82ed104
Flag that the directories have been set5aa535b
Add argument to arg parsing to not set directories367e5c3
Revert "Revert "When calling CMake, set the args and the cache""ab5d4e4
Revert "When calling CMake, set the args and the cache"9b90040
When calling CMake, set the args and the cachefe56002
Fix long lines for KWStyle5d30cfc
Set a watch on variables added through the gui33c63b1
Add a method to put a watch for variables535253f
Initialize the warning variables earliercbb286c
Fix the path detection to work for top-level62be1f7
Initialize the usage stack earlierc6e7fab
Factor out the checks for unused variables5e41ba8
When using the API, check for Add vs. Removedee1976
Fix typo in VariableUnusedViaUnset testf231ce5
Remove old false positive avoidance codea117e02
Revert "Add test for unused warnings at the end of scope"2c82f2b
Exempt CMAKE(CURRENT|PARENT)_LIST_FILE from usage6d7d449
Ignore CLI warnings for ABI determination7740a73
Only return local keys that are definedbef3aee
Use the API so that warnings can be tracked05cb0f4
Check for unused variables in the dtor91c4c99
Add test for unused warnings at the end of scopeca90f67
Fix detection of unused variables when settingf7438ca
Add test for unused detection via setting it995cfb0
Don't warn if the variable wasn't definedaefc91d
Add test for usage checks via unseta8e97f8
Remove VarRemoved code since it's been superceded59463ef
Rework CheckVariableForUnused usagef117423
Fix line lengths to be no more than 78e49a935
Improve unused warning logice01e40c
Mark ARGC, ARGV*, and ARGN as useda17aff7
Ignore CMAKE_MATCH_* variables for usage02a114d
Add method to allow variables to be marked as useda0b0d23
CMAKE_DO_TRY_COMPILE is no longer usedae3eff3
Fix the path used for ignoring system warnings056b441
Fix missing case for usage of a variable980e048
Factor out checks for unused variables83acb0a
Remove now unused variables3801463
Use built-ins for readability and maintainability8b52015
Push the initialize and unused states when copying439877f
Be consistent with single and double quotes4cf1706
Add documentation for check-system-varsb74777f
Fix the spelling of the flag for warn-unused-varsb948120
Change logic of flag to turn off cli unused checksf047a17
Add test for uninitialized variables75bda38
Add tests for unused command line variables300fc15
Fix detection of system filesd784e6a
Run the unused variables check on the final pass9efc057
VariableWatch is not available when bootstrapping2e78224
Add a missing comma to the warning message7499700
Add a flag to warn about system filesfff9f6d
Rename flags again and use variablewatch for cli786e269
Add warn-unused to the Qt interface636e6c4
Default to marking things as used4ff0340
Rename find-unused to warn-unusedd7999e9
Rename strict-mode to warn-uninitializede141bc9
Detect unused variablesd3e8eb5
Add flags to detect unused variablesf332e14
Complete strict-mode checks for uninitialized vars52f9637
Add method to get the local scope variablesf794d58
Make --strict-mode option, and integrate with cmake-gui48b5b85
Add a warning when variables are used uninitialized.cd626ea
For macros make sure the FilePath points to a valid pointer in the args.
This commit is contained in:
commit
182eb7c7ef
|
@ -24,10 +24,18 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ABI lang src)
|
|||
|
||||
# Compile the ABI identification source.
|
||||
SET(BIN "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeDetermineCompilerABI_${lang}.bin")
|
||||
SET(CMAKE_FLAGS )
|
||||
IF(DEFINED CMAKE_${lang}_VERBOSE_FLAG)
|
||||
SET(CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_${lang}_VERBOSE_FLAG}")
|
||||
ENDIF()
|
||||
TRY_COMPILE(CMAKE_DETERMINE_${lang}_ABI_COMPILED
|
||||
${CMAKE_BINARY_DIR} ${src}
|
||||
CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_${lang}_VERBOSE_FLAG}"
|
||||
CMAKE_FLAGS "${CMAKE_FLAGS}"
|
||||
"-DCMAKE_${lang}_STANDARD_LIBRARIES="
|
||||
# We need ignore these warnings because some platforms need
|
||||
# CMAKE_${lang}_STANDARD_LIBRARIES to link properly and we
|
||||
# don't care when we are just determining the ABI.
|
||||
"--no-warn-unused-cli"
|
||||
OUTPUT_VARIABLE OUTPUT
|
||||
COPY_FILE "${BIN}"
|
||||
)
|
||||
|
@ -58,10 +66,16 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ABI lang src)
|
|||
# Parse implicit linker information for this language, if available.
|
||||
SET(implicit_dirs "")
|
||||
SET(implicit_libs "")
|
||||
SET(MULTI_ARCH FALSE)
|
||||
IF(DEFINED CMAKE_OSX_ARCHITECTURES)
|
||||
IF( "${CMAKE_OSX_ARCHITECTURES}" MATCHES ";" )
|
||||
SET(MULTI_ARCH TRUE)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(CMAKE_${lang}_VERBOSE_FLAG
|
||||
# Implicit link information cannot be used explicitly for
|
||||
# multiple OS X architectures, so we skip it.
|
||||
AND NOT "${CMAKE_OSX_ARCHITECTURES}" MATCHES ";"
|
||||
AND NOT MULTI_ARCH
|
||||
# Skip this with Xcode for now.
|
||||
AND NOT "${CMAKE_GENERATOR}" MATCHES Xcode)
|
||||
CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs log
|
||||
|
|
|
@ -243,7 +243,9 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
|
|||
# ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface")
|
||||
|
||||
ENDIF(NOT CMAKE_EXECUTABLE_FORMAT)
|
||||
|
||||
IF(NOT DEFINED CMAKE_EXECUTABLE_FORMAT)
|
||||
SET(CMAKE_EXECUTABLE_FORMAT)
|
||||
ENDIF()
|
||||
# Return the information extracted.
|
||||
SET(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
|
||||
SET(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
|
||||
|
|
|
@ -789,6 +789,7 @@ void cmCursesMainForm::RemoveEntry(const char* value)
|
|||
const char* val = (*it)->GetValue();
|
||||
if ( val && !strcmp(value, val) )
|
||||
{
|
||||
this->CMakeInstance->UnwatchUnusedCli(value);
|
||||
this->Entries->erase(it);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -118,8 +118,15 @@ CMakeSetupDialog::CMakeSetupDialog()
|
|||
this, SLOT(doInstallForCommandLine()));
|
||||
#endif
|
||||
QMenu* OptionsMenu = this->menuBar()->addMenu(tr("&Options"));
|
||||
this->SuppressDevWarningsAction = OptionsMenu->addAction(tr("&Suppress dev Warnings (-Wno-dev)"));
|
||||
this->SuppressDevWarningsAction =
|
||||
OptionsMenu->addAction(tr("&Suppress dev Warnings (-Wno-dev)"));
|
||||
this->SuppressDevWarningsAction->setCheckable(true);
|
||||
this->WarnUninitializedAction =
|
||||
OptionsMenu->addAction(tr("&Warn Uninitialized (--warn-uninitialized)"));
|
||||
this->WarnUninitializedAction->setCheckable(true);
|
||||
this->WarnUnusedAction =
|
||||
OptionsMenu->addAction(tr("&Warn Unused (--warn-unused-vars)"));
|
||||
this->WarnUnusedAction->setCheckable(true);
|
||||
|
||||
QAction* debugAction = OptionsMenu->addAction(tr("&Debug Output"));
|
||||
debugAction->setCheckable(true);
|
||||
|
@ -247,6 +254,13 @@ void CMakeSetupDialog::initialize()
|
|||
QObject::connect(this->SuppressDevWarningsAction, SIGNAL(triggered(bool)),
|
||||
this->CMakeThread->cmakeInstance(), SLOT(setSuppressDevWarnings(bool)));
|
||||
|
||||
QObject::connect(this->WarnUninitializedAction, SIGNAL(triggered(bool)),
|
||||
this->CMakeThread->cmakeInstance(),
|
||||
SLOT(setWarnUninitializedMode(bool)));
|
||||
QObject::connect(this->WarnUnusedAction, SIGNAL(triggered(bool)),
|
||||
this->CMakeThread->cmakeInstance(),
|
||||
SLOT(setWarnUnusedMode(bool)));
|
||||
|
||||
if(!this->SourceDirectory->text().isEmpty() ||
|
||||
!this->BinaryDirectory->lineEdit()->text().isEmpty())
|
||||
{
|
||||
|
|
|
@ -97,6 +97,8 @@ protected:
|
|||
QAction* ConfigureAction;
|
||||
QAction* GenerateAction;
|
||||
QAction* SuppressDevWarningsAction;
|
||||
QAction* WarnUninitializedAction;
|
||||
QAction* WarnUnusedAction;
|
||||
QAction* InstallForCommandLineAction;
|
||||
State CurrentState;
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ QCMake::QCMake(QObject* p)
|
|||
: QObject(p)
|
||||
{
|
||||
this->SuppressDevWarnings = false;
|
||||
this->WarnUninitializedMode = false;
|
||||
this->WarnUnusedMode = false;
|
||||
qRegisterMetaType<QCMakeProperty>();
|
||||
qRegisterMetaType<QCMakePropertyList>();
|
||||
|
||||
|
@ -164,6 +166,8 @@ void QCMake::configure()
|
|||
this->CMakeInstance->CreateGlobalGenerator(this->Generator.toAscii().data()));
|
||||
this->CMakeInstance->LoadCache();
|
||||
this->CMakeInstance->SetSuppressDevWarnings(this->SuppressDevWarnings);
|
||||
this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);
|
||||
this->CMakeInstance->SetWarnUnused(this->WarnUnusedMode);
|
||||
this->CMakeInstance->PreLoadCMakeFiles();
|
||||
|
||||
cmSystemTools::ResetErrorOccuredFlag();
|
||||
|
@ -238,12 +242,16 @@ void QCMake::setProperties(const QCMakePropertyList& newProps)
|
|||
// remove some properites
|
||||
foreach(QString s, toremove)
|
||||
{
|
||||
this->CMakeInstance->UnwatchUnusedCli(s.toAscii().data());
|
||||
|
||||
cachem->RemoveCacheEntry(s.toAscii().data());
|
||||
}
|
||||
|
||||
// add some new properites
|
||||
foreach(QCMakeProperty s, props)
|
||||
{
|
||||
this->CMakeInstance->WatchUnusedCli(s.Key.toAscii().data());
|
||||
|
||||
if(s.Type == QCMakeProperty::BOOL)
|
||||
{
|
||||
this->CMakeInstance->AddCacheEntry(s.Key.toAscii().data(),
|
||||
|
@ -417,3 +425,13 @@ void QCMake::setSuppressDevWarnings(bool value)
|
|||
{
|
||||
this->SuppressDevWarnings = value;
|
||||
}
|
||||
|
||||
void QCMake::setWarnUninitializedMode(bool value)
|
||||
{
|
||||
this->WarnUninitializedMode = value;
|
||||
}
|
||||
|
||||
void QCMake::setWarnUnusedMode(bool value)
|
||||
{
|
||||
this->WarnUnusedMode = value;
|
||||
}
|
||||
|
|
|
@ -88,6 +88,10 @@ public slots:
|
|||
void setDebugOutput(bool);
|
||||
/// set whether to do suppress dev warnings
|
||||
void setSuppressDevWarnings(bool value);
|
||||
/// set whether to run cmake with warnings about uninitialized variables
|
||||
void setWarnUninitializedMode(bool value);
|
||||
/// set whether to run cmake with warnings about unused variables
|
||||
void setWarnUnusedMode(bool value);
|
||||
|
||||
public:
|
||||
/// get the list of cache properties
|
||||
|
@ -133,6 +137,9 @@ protected:
|
|||
static void errorCallback(const char* msg, const char* title,
|
||||
bool&, void* cd);
|
||||
bool SuppressDevWarnings;
|
||||
bool WarnUninitializedMode;
|
||||
bool WarnUnusedMode;
|
||||
bool WarnUnusedAllMode;
|
||||
QString SourceDirectory;
|
||||
QString BinaryDirectory;
|
||||
QString Generator;
|
||||
|
|
|
@ -20,6 +20,8 @@ int cmCommandArgument_yyparse( yyscan_t yyscanner );
|
|||
//
|
||||
cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
|
||||
{
|
||||
this->WarnUninitialized = false;
|
||||
this->CheckSystemVars = false;
|
||||
this->FileLine = -1;
|
||||
this->FileName = 0;
|
||||
this->RemoveEmpty = true;
|
||||
|
@ -119,10 +121,32 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
|
|||
cmOStringStream ostr;
|
||||
ostr << this->FileLine;
|
||||
return this->AddString(ostr.str().c_str());
|
||||
}
|
||||
}
|
||||
const char* value = this->Makefile->GetDefinition(var);
|
||||
if(!value && !this->RemoveEmpty)
|
||||
{
|
||||
// check to see if we need to print a warning
|
||||
// if strict mode is on and the variable has
|
||||
// not been "cleared"/initialized with a set(foo ) call
|
||||
if(this->WarnUninitialized && !this->Makefile->VariableInitialized(var))
|
||||
{
|
||||
if (this->CheckSystemVars ||
|
||||
cmSystemTools::IsSubDirectory(this->FileName,
|
||||
this->Makefile->GetHomeDirectory()) ||
|
||||
cmSystemTools::IsSubDirectory(this->FileName,
|
||||
this->Makefile->GetHomeOutputDirectory()))
|
||||
{
|
||||
cmOStringStream msg;
|
||||
cmListFileBacktrace bt;
|
||||
cmListFileContext lfc;
|
||||
lfc.FilePath = this->FileName;
|
||||
lfc.Line = this->FileLine;
|
||||
bt.push_back(lfc);
|
||||
msg << "uninitialized variable \'" << var << "\'";
|
||||
this->Makefile->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING,
|
||||
msg.str().c_str(), bt);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (this->EscapeQuotes && value)
|
||||
|
@ -319,6 +343,8 @@ void cmCommandArgumentParserHelper::Error(const char* str)
|
|||
void cmCommandArgumentParserHelper::SetMakefile(const cmMakefile* mf)
|
||||
{
|
||||
this->Makefile = mf;
|
||||
this->WarnUninitialized = mf->GetCMakeInstance()->GetWarnUninitialized();
|
||||
this->CheckSystemVars = mf->GetCMakeInstance()->GetCheckSystemVars();
|
||||
}
|
||||
|
||||
void cmCommandArgumentParserHelper::SetResult(const char* value)
|
||||
|
|
|
@ -96,6 +96,8 @@ private:
|
|||
const cmMakefile* Makefile;
|
||||
std::string Result;
|
||||
const char* FileName;
|
||||
bool WarnUninitialized;
|
||||
bool CheckSystemVars;
|
||||
long FileLine;
|
||||
bool EscapeQuotes;
|
||||
std::string ErrorString;
|
||||
|
|
|
@ -251,10 +251,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
|
|||
CMAKE_TRY_COMPILE_OSX_ARCHITECTURE first to i386 and then to ppc to
|
||||
have the tests run for each specific architecture. Since
|
||||
cmLocalGenerator doesn't allow building for "the other"
|
||||
architecture only via CMAKE_OSX_ARCHITECTURES,use to CMAKE_DO_TRY_COMPILE
|
||||
to enforce it for this case here.
|
||||
architecture only via CMAKE_OSX_ARCHITECTURES.
|
||||
*/
|
||||
cmakeFlags.push_back("-DCMAKE_DO_TRY_COMPILE=TRUE");
|
||||
if(this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_OSX_ARCHITECTURES")!=0)
|
||||
{
|
||||
std::string flag="-DCMAKE_OSX_ARCHITECTURES=";
|
||||
|
|
|
@ -84,6 +84,22 @@ const char* cmDefinitions::Set(const char* key, const char* value)
|
|||
return def.Exists? def.c_str() : 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::set<cmStdString> cmDefinitions::LocalKeys() const
|
||||
{
|
||||
std::set<cmStdString> keys;
|
||||
// Consider local definitions.
|
||||
for(MapType::const_iterator mi = this->Map.begin();
|
||||
mi != this->Map.end(); ++mi)
|
||||
{
|
||||
if (mi->second.Exists)
|
||||
{
|
||||
keys.insert(mi->first);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmDefinitions cmDefinitions::Closure() const
|
||||
{
|
||||
|
|
|
@ -40,6 +40,9 @@ public:
|
|||
/** Set (or unset if null) a value associated with a key. */
|
||||
const char* Set(const char* key, const char* value);
|
||||
|
||||
/** Get the set of all local keys. */
|
||||
std::set<cmStdString> LocalKeys() const;
|
||||
|
||||
/** Compute the closure of all defined keys with values.
|
||||
This flattens the scope. The result has no parent. */
|
||||
cmDefinitions Closure() const;
|
||||
|
|
|
@ -113,6 +113,7 @@ bool cmFunctionHelperCommand::InvokeInitialPass
|
|||
cmOStringStream strStream;
|
||||
strStream << expandedArgs.size();
|
||||
this->Makefile->AddDefinition("ARGC",strStream.str().c_str());
|
||||
this->Makefile->MarkVariableAsUsed("ARGC");
|
||||
|
||||
// set the values for ARGV0 ARGV1 ...
|
||||
for (unsigned int t = 0; t < expandedArgs.size(); ++t)
|
||||
|
@ -121,6 +122,7 @@ bool cmFunctionHelperCommand::InvokeInitialPass
|
|||
tmpStream << "ARGV" << t;
|
||||
this->Makefile->AddDefinition(tmpStream.str().c_str(),
|
||||
expandedArgs[t].c_str());
|
||||
this->Makefile->MarkVariableAsUsed(tmpStream.str().c_str());
|
||||
}
|
||||
|
||||
// define the formal arguments
|
||||
|
@ -153,7 +155,9 @@ bool cmFunctionHelperCommand::InvokeInitialPass
|
|||
cnt ++;
|
||||
}
|
||||
this->Makefile->AddDefinition("ARGV", argvDef.c_str());
|
||||
this->Makefile->MarkVariableAsUsed("ARGV");
|
||||
this->Makefile->AddDefinition("ARGN", argnDef.c_str());
|
||||
this->Makefile->MarkVariableAsUsed("ARGN");
|
||||
|
||||
// Invoke all the functions that were collected in the block.
|
||||
// for each function
|
||||
|
|
|
@ -903,6 +903,8 @@ void cmGlobalGenerator::Generate()
|
|||
}
|
||||
|
||||
this->CMakeInstance->UpdateProgress("Generating done", -1);
|
||||
|
||||
this->CMakeInstance->RunCheckForUnusedVariables("generation");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
// we must copy when we clone
|
||||
newC->Args = this->Args;
|
||||
newC->Functions = this->Functions;
|
||||
newC->FilePath = this->FilePath;
|
||||
newC->Policies = this->Policies;
|
||||
return newC;
|
||||
}
|
||||
|
@ -78,6 +79,7 @@ public:
|
|||
std::vector<std::string> Args;
|
||||
std::vector<cmListFileFunction> Functions;
|
||||
cmPolicies::PolicyMap Policies;
|
||||
std::string FilePath;
|
||||
};
|
||||
|
||||
|
||||
|
@ -121,7 +123,10 @@ bool cmMacroHelperCommand::InvokeInitialPass
|
|||
std::string argnDef;
|
||||
bool argnDefInitialized = false;
|
||||
bool argvDefInitialized = false;
|
||||
|
||||
if( this->Functions.size())
|
||||
{
|
||||
this->FilePath = this->Functions[0].FilePath;
|
||||
}
|
||||
// Invoke all the functions that were collected in the block.
|
||||
cmListFileFunction newLFF;
|
||||
// for each function
|
||||
|
@ -135,10 +140,13 @@ bool cmMacroHelperCommand::InvokeInitialPass
|
|||
newLFF.Line = this->Functions[c].Line;
|
||||
|
||||
// for each argument of the current function
|
||||
for (std::vector<cmListFileArgument>::const_iterator k =
|
||||
for (std::vector<cmListFileArgument>::iterator k =
|
||||
this->Functions[c].Arguments.begin();
|
||||
k != this->Functions[c].Arguments.end(); ++k)
|
||||
{
|
||||
// Set the FilePath on the arguments to match the function since it is
|
||||
// not stored and the original values may be freed
|
||||
k->FilePath = this->FilePath.c_str();
|
||||
tmps = k->Value;
|
||||
// replace formal arguments
|
||||
for (unsigned int j = 1; j < this->Args.size(); ++j)
|
||||
|
|
|
@ -112,7 +112,6 @@ public:
|
|||
"policies inside macros."
|
||||
;
|
||||
}
|
||||
|
||||
cmTypeMacro(cmMacroCommand, cmCommand);
|
||||
};
|
||||
|
||||
|
|
|
@ -44,12 +44,22 @@ class cmMakefile::Internals
|
|||
{
|
||||
public:
|
||||
std::stack<cmDefinitions, std::list<cmDefinitions> > VarStack;
|
||||
std::stack<std::set<cmStdString> > VarInitStack;
|
||||
std::stack<std::set<cmStdString> > VarUsageStack;
|
||||
};
|
||||
|
||||
// default is not to be building executables
|
||||
cmMakefile::cmMakefile(): Internal(new Internals)
|
||||
{
|
||||
this->Internal->VarStack.push(cmDefinitions());
|
||||
const cmDefinitions& defs = cmDefinitions();
|
||||
const std::set<cmStdString> globalKeys = defs.LocalKeys();
|
||||
this->Internal->VarStack.push(defs);
|
||||
this->Internal->VarInitStack.push(globalKeys);
|
||||
this->Internal->VarUsageStack.push(globalKeys);
|
||||
|
||||
// Initialize these first since AddDefaultDefinitions calls AddDefinition
|
||||
this->WarnUnused = false;
|
||||
this->CheckSystemVars = false;
|
||||
|
||||
// Setup the default include file regular expression (match everything).
|
||||
this->IncludeFileRegularExpression = "^.*$";
|
||||
|
@ -92,6 +102,8 @@ cmMakefile::cmMakefile(): Internal(new Internals)
|
|||
cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
|
||||
{
|
||||
this->Internal->VarStack.push(mf.Internal->VarStack.top().Closure());
|
||||
this->Internal->VarInitStack.push(mf.Internal->VarInitStack.top());
|
||||
this->Internal->VarUsageStack.push(mf.Internal->VarUsageStack.top());
|
||||
|
||||
this->Prefix = mf.Prefix;
|
||||
this->AuxSourceDirectories = mf.AuxSourceDirectories;
|
||||
|
@ -129,8 +141,10 @@ cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
|
|||
this->SubDirectoryOrder = mf.SubDirectoryOrder;
|
||||
this->Properties = mf.Properties;
|
||||
this->PreOrder = mf.PreOrder;
|
||||
this->ListFileStack = mf.ListFileStack;
|
||||
this->WarnUnused = mf.WarnUnused;
|
||||
this->Initialize();
|
||||
this->CheckSystemVars = mf.CheckSystemVars;
|
||||
this->ListFileStack = mf.ListFileStack;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -571,6 +585,7 @@ bool cmMakefile::ReadListFile(const char* filename_in,
|
|||
std::string currentFile
|
||||
= this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");
|
||||
this->AddDefinition("CMAKE_PARENT_LIST_FILE", filename_in);
|
||||
this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
|
||||
|
||||
const char* external = 0;
|
||||
std::string external_abs;
|
||||
|
@ -611,8 +626,10 @@ bool cmMakefile::ReadListFile(const char* filename_in,
|
|||
}
|
||||
|
||||
this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread);
|
||||
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
|
||||
this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
|
||||
cmSystemTools::GetFilenamePath(filenametoread).c_str());
|
||||
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
|
||||
|
||||
// try to see if the list file is the top most
|
||||
// list file for a project, and if it is, then it
|
||||
|
@ -645,9 +662,12 @@ bool cmMakefile::ReadListFile(const char* filename_in,
|
|||
*fullPath = "";
|
||||
}
|
||||
this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
|
||||
this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
|
||||
this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
|
||||
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
|
||||
this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
|
||||
cmSystemTools::GetFilenamePath(currentFile).c_str());
|
||||
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
|
||||
return false;
|
||||
}
|
||||
// add this list file to the list of dependencies
|
||||
|
@ -687,13 +707,19 @@ bool cmMakefile::ReadListFile(const char* filename_in,
|
|||
}
|
||||
|
||||
this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
|
||||
this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
|
||||
this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
|
||||
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
|
||||
this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
|
||||
cmSystemTools::GetFilenamePath(currentFile).c_str());
|
||||
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
|
||||
|
||||
// pop the listfile off the stack
|
||||
this->ListFileStack.pop_back();
|
||||
|
||||
// Check for unused variables
|
||||
this->CheckForUnusedVariables();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -759,6 +785,8 @@ void cmMakefile::SetLocalGenerator(cmLocalGenerator* lg)
|
|||
this->AddSourceGroup("Resources", "\\.plist$");
|
||||
#endif
|
||||
|
||||
this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
|
||||
this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();
|
||||
}
|
||||
|
||||
bool cmMakefile::NeedBackwardsCompatibility(unsigned int major,
|
||||
|
@ -1627,6 +1655,13 @@ void cmMakefile::AddDefinition(const char* name, const char* value)
|
|||
#endif
|
||||
|
||||
this->Internal->VarStack.top().Set(name, value);
|
||||
if (this->Internal->VarUsageStack.size() &&
|
||||
this->VariableInitialized(name))
|
||||
{
|
||||
this->CheckForUnused("changing definition", name);
|
||||
this->Internal->VarUsageStack.top().erase(name);
|
||||
}
|
||||
this->Internal->VarInitStack.top().insert(name);
|
||||
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
cmVariableWatch* vv = this->GetVariableWatch();
|
||||
|
@ -1691,6 +1726,13 @@ void cmMakefile::AddCacheDefinition(const char* name, const char* value,
|
|||
void cmMakefile::AddDefinition(const char* name, bool value)
|
||||
{
|
||||
this->Internal->VarStack.top().Set(name, value? "ON" : "OFF");
|
||||
if (this->Internal->VarUsageStack.size() &&
|
||||
this->VariableInitialized(name))
|
||||
{
|
||||
this->CheckForUnused("changing definition", name);
|
||||
this->Internal->VarUsageStack.top().erase(name);
|
||||
}
|
||||
this->Internal->VarInitStack.top().insert(name);
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
cmVariableWatch* vv = this->GetVariableWatch();
|
||||
if ( vv )
|
||||
|
@ -1701,9 +1743,90 @@ void cmMakefile::AddDefinition(const char* name, bool value)
|
|||
#endif
|
||||
}
|
||||
|
||||
void cmMakefile::CheckForUnusedVariables() const
|
||||
{
|
||||
const cmDefinitions& defs = this->Internal->VarStack.top();
|
||||
const std::set<cmStdString>& locals = defs.LocalKeys();
|
||||
std::set<cmStdString>::const_iterator it = locals.begin();
|
||||
for (; it != locals.end(); ++it)
|
||||
{
|
||||
this->CheckForUnused("out of scope", it->c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void cmMakefile::MarkVariableAsUsed(const char* var)
|
||||
{
|
||||
this->Internal->VarUsageStack.top().insert(var);
|
||||
}
|
||||
|
||||
bool cmMakefile::VariableInitialized(const char* var) const
|
||||
{
|
||||
if(this->Internal->VarInitStack.top().find(var) !=
|
||||
this->Internal->VarInitStack.top().end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmMakefile::VariableUsed(const char* var) const
|
||||
{
|
||||
if(this->Internal->VarUsageStack.top().find(var) !=
|
||||
this->Internal->VarUsageStack.top().end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cmMakefile::CheckForUnused(const char* reason, const char* name) const
|
||||
{
|
||||
if (this->WarnUnused && !this->VariableUsed(name))
|
||||
{
|
||||
cmStdString path;
|
||||
cmListFileBacktrace bt;
|
||||
if (this->CallStack.size())
|
||||
{
|
||||
const cmListFileContext* file = this->CallStack.back().Context;
|
||||
bt.push_back(*file);
|
||||
path = file->FilePath.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
path = this->GetStartDirectory();
|
||||
path += "/CMakeLists.txt";
|
||||
cmListFileContext lfc;
|
||||
lfc.FilePath = path;
|
||||
lfc.Line = 0;
|
||||
bt.push_back(lfc);
|
||||
}
|
||||
if (this->CheckSystemVars ||
|
||||
cmSystemTools::IsSubDirectory(path.c_str(),
|
||||
this->GetHomeDirectory()) ||
|
||||
(cmSystemTools::IsSubDirectory(path.c_str(),
|
||||
this->GetHomeOutputDirectory()) &&
|
||||
!cmSystemTools::IsSubDirectory(path.c_str(),
|
||||
cmake::GetCMakeFilesDirectory())))
|
||||
{
|
||||
cmOStringStream msg;
|
||||
msg << "unused variable (" << reason << ") \'" << name << "\'";
|
||||
this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING,
|
||||
msg.str().c_str(),
|
||||
bt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmMakefile::RemoveDefinition(const char* name)
|
||||
{
|
||||
this->Internal->VarStack.top().Set(name, 0);
|
||||
if (this->Internal->VarUsageStack.size() &&
|
||||
this->VariableInitialized(name))
|
||||
{
|
||||
this->CheckForUnused("unsetting", name);
|
||||
this->Internal->VarUsageStack.top().erase(name);
|
||||
}
|
||||
this->Internal->VarInitStack.top().insert(name);
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
cmVariableWatch* vv = this->GetVariableWatch();
|
||||
if ( vv )
|
||||
|
@ -2055,6 +2178,7 @@ const char* cmMakefile::GetRequiredDefinition(const char* name) const
|
|||
bool cmMakefile::IsDefinitionSet(const char* name) const
|
||||
{
|
||||
const char* def = this->Internal->VarStack.top().Get(name);
|
||||
this->Internal->VarUsageStack.top().insert(name);
|
||||
if(!def)
|
||||
{
|
||||
def = this->GetCacheManager()->GetCacheValue(name);
|
||||
|
@ -2082,6 +2206,10 @@ const char* cmMakefile::GetDefinition(const char* name) const
|
|||
RecordPropertyAccess(name,cmProperty::VARIABLE);
|
||||
}
|
||||
#endif
|
||||
if (this->WarnUnused)
|
||||
{
|
||||
this->Internal->VarUsageStack.top().insert(name);
|
||||
}
|
||||
const char* def = this->Internal->VarStack.top().Get(name);
|
||||
if(!def)
|
||||
{
|
||||
|
@ -2733,6 +2861,31 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir,
|
|||
// if cmake args were provided then pass them in
|
||||
if (cmakeArgs)
|
||||
{
|
||||
// FIXME: Workaround to ignore unused CLI variables in try-compile.
|
||||
//
|
||||
// Ideally we should use SetArgs to honor options like --warn-unused-vars.
|
||||
// However, there is a subtle problem when certain arguments are passed to
|
||||
// a macro wrapping around try_compile or try_run that does not escape
|
||||
// semicolons in its parameters but just passes ${ARGV} or ${ARGN}. In
|
||||
// this case a list argument like "-DVAR=a;b" gets split into multiple
|
||||
// cmake arguments "-DVAR=a" and "b". Currently SetCacheArgs ignores
|
||||
// argument "b" and uses just "-DVAR=a", leading to a subtle bug in that
|
||||
// the try_compile or try_run does not get the proper value of VAR. If we
|
||||
// call SetArgs here then it would treat "b" as the source directory and
|
||||
// cause an error such as "The source directory .../CMakeFiles/CMakeTmp/b
|
||||
// does not exist", thus breaking the try_compile or try_run completely.
|
||||
//
|
||||
// Strictly speaking the bug is in the wrapper macro because the CMake
|
||||
// language has always flattened nested lists and the macro should escape
|
||||
// the semicolons in its arguments before forwarding them. However, this
|
||||
// bug is so subtle that projects typically work anyway, usually because
|
||||
// the value VAR=a is sufficient for the try_compile or try_run to get the
|
||||
// correct result. Calling SetArgs here would break such projects that
|
||||
// previously built. Instead we work around the issue by never reporting
|
||||
// unused arguments and ignoring options such as --warn-unused-vars.
|
||||
cm.SetWarnUnusedCli(false);
|
||||
//cm.SetArgs(*cmakeArgs, true);
|
||||
|
||||
cm.SetCacheArgs(*cmakeArgs);
|
||||
}
|
||||
// to save time we pass the EnableLanguage info directly
|
||||
|
@ -3416,12 +3569,48 @@ std::string cmMakefile::GetListFileStack()
|
|||
void cmMakefile::PushScope()
|
||||
{
|
||||
cmDefinitions* parent = &this->Internal->VarStack.top();
|
||||
const std::set<cmStdString>& init = this->Internal->VarInitStack.top();
|
||||
const std::set<cmStdString>& usage = this->Internal->VarUsageStack.top();
|
||||
this->Internal->VarStack.push(cmDefinitions(parent));
|
||||
this->Internal->VarInitStack.push(init);
|
||||
this->Internal->VarUsageStack.push(usage);
|
||||
}
|
||||
|
||||
void cmMakefile::PopScope()
|
||||
{
|
||||
cmDefinitions* current = &this->Internal->VarStack.top();
|
||||
std::set<cmStdString> init = this->Internal->VarInitStack.top();
|
||||
std::set<cmStdString> usage = this->Internal->VarUsageStack.top();
|
||||
const std::set<cmStdString>& locals = current->LocalKeys();
|
||||
// Remove initialization and usage information for variables in the local
|
||||
// scope.
|
||||
std::set<cmStdString>::const_iterator it = locals.begin();
|
||||
for (; it != locals.end(); ++it)
|
||||
{
|
||||
init.erase(*it);
|
||||
if (!this->VariableUsed(it->c_str()))
|
||||
{
|
||||
this->CheckForUnused("out of scope", it->c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
usage.erase(*it);
|
||||
}
|
||||
}
|
||||
this->Internal->VarStack.pop();
|
||||
this->Internal->VarInitStack.pop();
|
||||
this->Internal->VarUsageStack.pop();
|
||||
// Push initialization and usage up to the parent scope.
|
||||
it = init.begin();
|
||||
for (; it != init.end(); ++it)
|
||||
{
|
||||
this->Internal->VarInitStack.top().insert(*it);
|
||||
}
|
||||
it = usage.begin();
|
||||
for (; it != usage.end(); ++it)
|
||||
{
|
||||
this->Internal->VarUsageStack.top().insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void cmMakefile::RaiseScope(const char *var, const char *varDef)
|
||||
|
@ -3446,7 +3635,14 @@ void cmMakefile::RaiseScope(const char *var, const char *varDef)
|
|||
// directory's scope was initialized by the closure of the parent
|
||||
// scope, so we do not need to localize the definition first.
|
||||
cmMakefile* parent = plg->GetMakefile();
|
||||
parent->Internal->VarStack.top().Set(var, varDef);
|
||||
if (varDef)
|
||||
{
|
||||
parent->AddDefinition(var, varDef);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->RemoveDefinition(var);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -61,6 +61,14 @@ public:
|
|||
unsigned int GetCacheMajorVersion();
|
||||
unsigned int GetCacheMinorVersion();
|
||||
|
||||
/* Check for unused variables in this scope */
|
||||
void CheckForUnusedVariables() const;
|
||||
/* Mark a variable as used */
|
||||
void MarkVariableAsUsed(const char* var);
|
||||
/* return true if a variable has been initialized */
|
||||
bool VariableInitialized(const char* ) const;
|
||||
/* return true if a variable has been used */
|
||||
bool VariableUsed(const char* ) const;
|
||||
/** Return whether compatibility features needed for a version of
|
||||
the cache or lower should be enabled. */
|
||||
bool NeedCacheCompatibility(int major, int minor);
|
||||
|
@ -836,7 +844,10 @@ public:
|
|||
protected:
|
||||
// add link libraries and directories to the target
|
||||
void AddGlobalLinkInformation(const char* name, cmTarget& target);
|
||||
|
||||
|
||||
// Check for a an unused variable
|
||||
void CheckForUnused(const char* reason, const char* name) const;
|
||||
|
||||
std::string Prefix;
|
||||
std::vector<std::string> AuxSourceDirectories; //
|
||||
|
||||
|
@ -929,6 +940,10 @@ private:
|
|||
// should this makefile be processed before or after processing the parent
|
||||
bool PreOrder;
|
||||
|
||||
// Unused variable flags
|
||||
bool WarnUnused;
|
||||
bool CheckSystemVars;
|
||||
|
||||
// stack of list files being read
|
||||
std::deque<cmStdString> ListFileStack;
|
||||
|
||||
|
|
|
@ -482,6 +482,7 @@ void cmStringCommand::ClearMatches(cmMakefile* mf)
|
|||
char name[128];
|
||||
sprintf(name, "CMAKE_MATCH_%d", i);
|
||||
mf->AddDefinition(name, "");
|
||||
mf->MarkVariableAsUsed(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -493,6 +494,7 @@ void cmStringCommand::StoreMatches(cmMakefile* mf,cmsys::RegularExpression& re)
|
|||
char name[128];
|
||||
sprintf(name, "CMAKE_MATCH_%d", i);
|
||||
mf->AddDefinition(name, re.match(i).c_str());
|
||||
mf->MarkVariableAsUsed(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,9 +138,20 @@ void cmNeedBackwardsCompatibility(const std::string& variable,
|
|||
#endif
|
||||
}
|
||||
|
||||
void cmWarnUnusedCliWarning(const std::string& variable,
|
||||
int, void* ctx, const char*, const cmMakefile*)
|
||||
{
|
||||
cmake* cm = reinterpret_cast<cmake*>(ctx);
|
||||
cm->MarkCliAsUsed(variable);
|
||||
}
|
||||
|
||||
cmake::cmake()
|
||||
{
|
||||
this->Trace = false;
|
||||
this->WarnUninitialized = false;
|
||||
this->WarnUnused = false;
|
||||
this->WarnUnusedCli = true;
|
||||
this->CheckSystemVars = false;
|
||||
this->SuppressDevWarnings = false;
|
||||
this->DoSuppressDevWarnings = false;
|
||||
this->DebugOutput = false;
|
||||
|
@ -367,6 +378,10 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
|
|||
{
|
||||
this->CacheManager->AddCacheEntry(var.c_str(), value.c_str(),
|
||||
"No help, variable specified on the command line.", type);
|
||||
if(this->WarnUnusedCli)
|
||||
{
|
||||
this->WatchUnusedCli(var.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -509,9 +524,10 @@ void cmake::ReadListFile(const char *path)
|
|||
}
|
||||
|
||||
// Parse the args
|
||||
void cmake::SetArgs(const std::vector<std::string>& args)
|
||||
void cmake::SetArgs(const std::vector<std::string>& args,
|
||||
bool directoriesSetBefore)
|
||||
{
|
||||
bool directoriesSet = false;
|
||||
bool directoriesSet = directoriesSetBefore;
|
||||
for(unsigned int i=1; i < args.size(); ++i)
|
||||
{
|
||||
std::string arg = args[i];
|
||||
|
@ -613,6 +629,28 @@ void cmake::SetArgs(const std::vector<std::string>& args)
|
|||
std::cout << "Running with trace output on.\n";
|
||||
this->SetTrace(true);
|
||||
}
|
||||
else if(arg.find("--warn-uninitialized",0) == 0)
|
||||
{
|
||||
std::cout << "Warn about uninitialized values.\n";
|
||||
this->SetWarnUninitialized(true);
|
||||
}
|
||||
else if(arg.find("--warn-unused-vars",0) == 0)
|
||||
{
|
||||
std::cout << "Finding unused variables.\n";
|
||||
this->SetWarnUnused(true);
|
||||
}
|
||||
else if(arg.find("--no-warn-unused-cli",0) == 0)
|
||||
{
|
||||
std::cout << "Not searching for unused variables given on the " <<
|
||||
"command line.\n";
|
||||
this->SetWarnUnusedCli(false);
|
||||
}
|
||||
else if(arg.find("--check-system-vars",0) == 0)
|
||||
{
|
||||
std::cout << "Also check system files when warning about unused and " <<
|
||||
"uninitialized variables.\n";
|
||||
this->SetCheckSystemVars(true);
|
||||
}
|
||||
else if(arg.find("-G",0) == 0)
|
||||
{
|
||||
std::string value = arg.substr(2);
|
||||
|
@ -2272,6 +2310,11 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
|
|||
std::string oldstartoutputdir = this->GetStartOutputDirectory();
|
||||
this->SetStartDirectory(this->GetHomeDirectory());
|
||||
this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
|
||||
const bool warncli = this->WarnUnusedCli;
|
||||
if (!this->ScriptMode)
|
||||
{
|
||||
this->WarnUnusedCli = false;
|
||||
}
|
||||
int ret = this->Configure();
|
||||
if (ret || this->ScriptMode)
|
||||
{
|
||||
|
@ -2293,6 +2336,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
|
|||
#endif
|
||||
return ret;
|
||||
}
|
||||
this->WarnUnusedCli = warncli;
|
||||
ret = this->Generate();
|
||||
std::string message = "Build files have been written to: ";
|
||||
message += this->GetHomeOutputDirectory();
|
||||
|
@ -2835,6 +2879,10 @@ const char* cmake::GetCPackCommand()
|
|||
return this->CPackCommand.c_str();
|
||||
}
|
||||
|
||||
void cmake::MarkCliAsUsed(const std::string& variable)
|
||||
{
|
||||
this->UsedCliVariables[variable] = true;
|
||||
}
|
||||
|
||||
void cmake::GenerateGraphViz(const char* fileName) const
|
||||
{
|
||||
|
@ -4255,3 +4303,40 @@ int cmake::Build(const std::string& dir,
|
|||
config.c_str(), clean, false, 0, true,
|
||||
0, nativeOptions);
|
||||
}
|
||||
|
||||
void cmake::WatchUnusedCli(const char* var)
|
||||
{
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
this->VariableWatch->AddWatch(var, cmWarnUnusedCliWarning, this);
|
||||
this->UsedCliVariables[var] = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void cmake::UnwatchUnusedCli(const char* var)
|
||||
{
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
this->VariableWatch->RemoveWatch(var, cmWarnUnusedCliWarning);
|
||||
this->UsedCliVariables[var] = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void cmake::RunCheckForUnusedVariables(const std::string& reason) const
|
||||
{
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
if(this->WarnUnusedCli)
|
||||
{
|
||||
std::map<std::string, bool>::const_iterator it;
|
||||
for(it = this->UsedCliVariables.begin();
|
||||
it != this->UsedCliVariables.end(); ++it)
|
||||
{
|
||||
if(!it->second)
|
||||
{
|
||||
std::string message = "CMake Warning: The variable, '" + it->first +
|
||||
"', specified manually, was not used during the " + reason +
|
||||
".";
|
||||
cmSystemTools::Message(message.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -214,7 +214,8 @@ class cmake
|
|||
bool CommandExists(const char* name) const;
|
||||
|
||||
///! Parse command line arguments
|
||||
void SetArgs(const std::vector<std::string>&);
|
||||
void SetArgs(const std::vector<std::string>&,
|
||||
bool directoriesSetBefore = false);
|
||||
|
||||
///! Is this cmake running as a result of a TRY_COMPILE command
|
||||
bool GetIsInTryCompile() { return this->InTryCompile; }
|
||||
|
@ -308,6 +309,17 @@ class cmake
|
|||
// Do we want trace output during the cmake run.
|
||||
bool GetTrace() { return this->Trace;}
|
||||
void SetTrace(bool b) { this->Trace = b;}
|
||||
bool GetWarnUninitialized() { return this->WarnUninitialized;}
|
||||
void SetWarnUninitialized(bool b) { this->WarnUninitialized = b;}
|
||||
bool GetWarnUnused() { return this->WarnUnused;}
|
||||
void SetWarnUnused(bool b) { this->WarnUnused = b;}
|
||||
bool GetWarnUnusedCli() { return this->WarnUnusedCli;}
|
||||
void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b;}
|
||||
bool GetCheckSystemVars() { return this->CheckSystemVars;}
|
||||
void SetCheckSystemVars(bool b) { this->CheckSystemVars = b;}
|
||||
|
||||
void MarkCliAsUsed(const std::string& variable);
|
||||
|
||||
// Define a property
|
||||
void DefineProperty(const char *name, cmProperty::ScopeType scope,
|
||||
const char *ShortDescription,
|
||||
|
@ -353,6 +365,10 @@ class cmake
|
|||
const std::string& config,
|
||||
const std::vector<std::string>& nativeOptions,
|
||||
bool clean);
|
||||
|
||||
void UnwatchUnusedCli(const char* var);
|
||||
void WatchUnusedCli(const char* var);
|
||||
void RunCheckForUnusedVariables(const std::string& reason) const;
|
||||
protected:
|
||||
void InitializeProperties();
|
||||
int HandleDeleteCacheVariables(const char* var);
|
||||
|
@ -445,6 +461,11 @@ private:
|
|||
bool ScriptMode;
|
||||
bool DebugOutput;
|
||||
bool Trace;
|
||||
bool WarnUninitialized;
|
||||
bool WarnUnused;
|
||||
bool WarnUnusedCli;
|
||||
bool CheckSystemVars;
|
||||
std::map<std::string, bool> UsedCliVariables;
|
||||
std::string CMakeEditCommand;
|
||||
std::string CMakeCommand;
|
||||
std::string CXXEnvironment;
|
||||
|
|
|
@ -120,6 +120,17 @@ static const char * cmDocumentationOptions[][3] =
|
|||
{"--trace", "Put cmake in trace mode.",
|
||||
"Print a trace of all calls made and from where with "
|
||||
"message(send_error ) calls."},
|
||||
{"--warn-uninitialized", "Warn about uninitialized values.",
|
||||
"Print a warning when an uninitialized variable is used."},
|
||||
{"--warn-unused-vars", "Warn about unused variables.",
|
||||
"Find variables that are declared or set, but not used."},
|
||||
{"--no-warn-unused-cli", "Don't warn about command line options.",
|
||||
"Don't find variables that are declared on the command line, but not "
|
||||
"used."},
|
||||
{"--check-system-vars", "Find problems with variable usage in system "
|
||||
"files.", "Normally, unused and uninitialized variables are searched for "
|
||||
"only in CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR. This flag tells CMake to "
|
||||
"warn about other files as well."},
|
||||
{"--help-command cmd [file]", "Print help for a single command and exit.",
|
||||
"Full documentation specific to the given command is displayed. "
|
||||
"If a file is specified, the documentation is written into and the output "
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(ArgumentExpansion)
|
||||
|
||||
function (argument_tester expected expected_len)
|
||||
list(LENGTH ARGN argn_len)
|
||||
list(LENGTH ${expected} expected_received_len)
|
||||
|
||||
if (NOT ${expected_received_len} EQUAL ${expected_len})
|
||||
message(STATUS "Unexpected: Expanding expected values isn't working")
|
||||
endif (NOT ${expected_received_len} EQUAL ${expected_len})
|
||||
|
||||
if (${argn_len} EQUAL ${expected_len})
|
||||
set(i 0)
|
||||
while (i LESS ${argn_len})
|
||||
list(GET ARGN ${i} argn_value)
|
||||
list(GET ${expected} ${i} expected_value)
|
||||
|
||||
if (NOT "${argn_value}" STREQUAL "${expected_value}")
|
||||
message(STATUS "Unexpected: Argument ${i} doesn't match")
|
||||
message(STATUS " Expected: ${expected_value}")
|
||||
message(STATUS " Received: ${argn_value}")
|
||||
endif ()
|
||||
|
||||
math(EXPR i "${i} + 1")
|
||||
endwhile (i LESS ${argn_len})
|
||||
else (${argn_len} EQUAL ${expected_len})
|
||||
message(STATUS "Unexpected: Lengths of arguments don't match")
|
||||
message(STATUS " Expected: ${expected_len}")
|
||||
message(STATUS " Received: ${argn_len}")
|
||||
endif (${argn_len} EQUAL ${expected_len})
|
||||
endfunction (argument_tester expected)
|
||||
|
||||
set(empty_test)
|
||||
message(STATUS "Test: Empty arguments")
|
||||
argument_tester(empty_test 0 ${empty_test})
|
||||
|
||||
set(single_arg_test
|
||||
"single arg")
|
||||
message(STATUS "Test: Single argument")
|
||||
argument_tester(single_arg_test 1 ${single_arg_test})
|
||||
|
||||
set(multiple_arg_test
|
||||
"first arg"
|
||||
"second arg")
|
||||
message(STATUS "Test: Multiple arguments")
|
||||
argument_tester(multiple_arg_test 2 ${multiple_arg_test})
|
||||
|
||||
set(nested_list_arg_test
|
||||
"${multiple_arg_test}"
|
||||
"first arg"
|
||||
"second arg")
|
||||
message(STATUS "Test: Nested list argument flattens")
|
||||
argument_tester(nested_list_arg_test 4 ${nested_list_arg_test})
|
||||
|
||||
set(semicolon_arg_test
|
||||
"pre\;post")
|
||||
set(semicolon_arg_test_flat "pre;post")
|
||||
message(STATUS "Test: Semicolon argument flattens")
|
||||
argument_tester(semicolon_arg_test_flat 2 ${semicolon_arg_test})
|
|
@ -391,6 +391,19 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
|
|||
)
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CustComDepend")
|
||||
|
||||
ADD_TEST(ArgumentExpansion ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/ArgumentExpansion"
|
||||
"${CMake_BINARY_DIR}/Tests/ArgumentExpansion"
|
||||
--build-generator ${CMAKE_TEST_GENERATOR}
|
||||
--build-project ArgumentExpansion
|
||||
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
|
||||
--build-exe-dir "${CMake_BINARY_DIR}/Tests/ArgumentExpansion/bin"
|
||||
)
|
||||
SET_TESTS_PROPERTIES(ArgumentExpansion PROPERTIES
|
||||
FAIL_REGULAR_EXPRESSION "Unexpected: ")
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ArgumentExpansion")
|
||||
|
||||
ADD_TEST(CustomCommand ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/CustomCommand"
|
||||
|
@ -1139,6 +1152,77 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
|
|||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BundleGeneratorTest")
|
||||
ENDIF(APPLE AND CTEST_TEST_CPACK)
|
||||
|
||||
ADD_TEST(WarnUnusedUnusedViaSet ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/VariableUnusedViaSet"
|
||||
"${CMake_BINARY_DIR}/Tests/WarnUnusedUnusedViaSet"
|
||||
--build-generator ${CMAKE_TEST_GENERATOR}
|
||||
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
|
||||
--build-noclean
|
||||
--build-project WarnUnusedUnusedViaSet
|
||||
--build-options "--warn-unused-vars")
|
||||
SET_TESTS_PROPERTIES(WarnUnusedUnusedViaSet PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "unused variable \\(changing definition\\) 'UNUSED_VARIABLE'")
|
||||
SET_TESTS_PROPERTIES(WarnUnusedUnusedViaSet PROPERTIES
|
||||
FAIL_REGULAR_EXPRESSION "unused variable \\(unsetting\\) 'UNUSED_VARIABLE'")
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/WarnUnusedUnusedViaSet")
|
||||
|
||||
ADD_TEST(WarnUnusedUnusedViaUnset ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/VariableUnusedViaUnset"
|
||||
"${CMake_BINARY_DIR}/Tests/WarnUnusedUnusedViaUnset"
|
||||
--build-generator ${CMAKE_TEST_GENERATOR}
|
||||
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
|
||||
--build-noclean
|
||||
--build-project WarnUnusedUnusedViaUnset
|
||||
--build-options "--warn-unused-vars")
|
||||
SET_TESTS_PROPERTIES(WarnUnusedUnusedViaUnset PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "CMake Warning .*:7 \\(set\\):")
|
||||
SET_TESTS_PROPERTIES(WarnUnusedUnusedViaUnset PROPERTIES
|
||||
FAIL_REGULAR_EXPRESSION "CMake Warning .*:5 \\(set\\):")
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/WarnUnusedUnusedViaUnset")
|
||||
|
||||
ADD_TEST(WarnUnusedCliUnused ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/VariableUsage"
|
||||
"${CMake_BINARY_DIR}/Tests/WarnUnusedCliUnused"
|
||||
--build-generator ${CMAKE_TEST_GENERATOR}
|
||||
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
|
||||
--build-noclean
|
||||
--build-project WarnUnusedCliUnused
|
||||
--build-options "-DUNUSED_CLI_VARIABLE=Unused")
|
||||
SET_TESTS_PROPERTIES(WarnUnusedCliUnused PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "CMake Warning: The variable, 'UNUSED_CLI_VARIABLE'")
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/WarnUnusedCliUnused")
|
||||
|
||||
ADD_TEST(WarnUnusedCliUsed ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/VariableUsage"
|
||||
"${CMake_BINARY_DIR}/Tests/WarnUnusedCliUsed"
|
||||
--build-generator ${CMAKE_TEST_GENERATOR}
|
||||
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
|
||||
--build-noclean
|
||||
--build-project WarnUnusedCliUsed
|
||||
--build-options "-DUSED_VARIABLE=Usage proven")
|
||||
SET_TESTS_PROPERTIES(WarnUnusedCliUsed PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "Usage proven")
|
||||
SET_TESTS_PROPERTIES(WarnUnusedCliUsed PROPERTIES
|
||||
FAIL_REGULAR_EXPRESSION "CMake Warning: The variable, 'USED_VARIABLE'")
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/WarnUnusedCliUsed")
|
||||
|
||||
ADD_TEST(WarnUninitialized ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/VariableUsage"
|
||||
"${CMake_BINARY_DIR}/Tests/WarnUninitialized"
|
||||
--build-generator ${CMAKE_TEST_GENERATOR}
|
||||
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
|
||||
--build-noclean
|
||||
--build-project WarnUninitialized
|
||||
--build-options "--warn-uninitialized")
|
||||
SET_TESTS_PROPERTIES(WarnUninitialized PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "uninitialized variable 'USED_VARIABLE'")
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/WarnUninitialized")
|
||||
|
||||
ADD_TEST(TestsWorkingDirectory ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/TestsWorkingDirectory"
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
set(UNUSED_VARIABLE)
|
||||
# Warning should occur here
|
||||
set(UNUSED_VARIABLE "Usage")
|
||||
message(STATUS "${UNUSED_VARIABLE}")
|
|
@ -0,0 +1,8 @@
|
|||
# NOTE: Changing lines in here changes the test results since the first
|
||||
# instance shouldn't warn, but the second should and they have the same message
|
||||
|
||||
# A warning should NOT be issued for this line:
|
||||
set(UNUSED_VARIABLE)
|
||||
# Warning should occur here:
|
||||
set(UNUSED_VARIABLE)
|
||||
message(STATUS "${UNUSED_VARIABLE}")
|
|
@ -0,0 +1 @@
|
|||
message(STATUS "${USED_VARIABLE}")
|
Loading…
Reference in New Issue