mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-06 21:59:54 -06:00
Merge topic 'dev/strict-mode'
dd2f814Merge branch 'dev/add_test-working-directory' into dev/strict-mode949d32cUnwatch manual variables upon removal in cmake-gui3939032Unwatch manual variables upon removal in ccmake8354413Add method to unwatch a manual variable8ed3c85Give a better message for unused variables729db48Fix ArgumentExpansion test expected results89c2544Checking for a definition is a usage5625deeDon't output to stderr in the GUIad25a96Merge branch 'ImprovedDotSupport2' into dev/strict-modec128abeMerge branch 'AddCMAKE_CURRENT_LIST_DIR' into dev/strict-mode9bcaff0Merge branch 'cmake-guiRememberAdvancedCheckbox' into dev/strict-mode544d0c3Fix expected output for WarnUninitialized test4e3bea4Update expected messages to new format8e8c9e4Don't check at destruction for usage668e005Use cmake::IssueMessage for warnings88cd4c1Use 'CMake Warning' versus 'warning' for CDash3c3b98dInitialize the class before setting warn flagscf8b15aIgnore files under the CMakeFiles directoryfd50f06Don't check for unused vars at configure time447a04cDon't warn during configure when doing everythingb97ee21Check for unused variables at the end of generatec18c977When checking for variables, specify a reason3f1121fUse a long int since Line is a long as well2507f93Change the failure case string to 'Unexpected'fe390a2Add 'ArgumentExpansion' test8dbb209Wrong boolean value for CLI warningsd4ee998Hard-code the --no-warn-unused-cli flaga267b99Fix line lengths82ed104Flag that the directories have been set5aa535bAdd argument to arg parsing to not set directories367e5c3Revert "Revert "When calling CMake, set the args and the cache""ab5d4e4Revert "When calling CMake, set the args and the cache"9b90040When calling CMake, set the args and the cachefe56002Fix long lines for KWStyle5d30cfcSet a watch on variables added through the gui33c63b1Add a method to put a watch for variables535253fInitialize the warning variables earliercbb286cFix the path detection to work for top-level62be1f7Initialize the usage stack earlierc6e7fabFactor out the checks for unused variables5e41ba8When using the API, check for Add vs. Removedee1976Fix typo in VariableUnusedViaUnset testf231ce5Remove old false positive avoidance codea117e02Revert "Add test for unused warnings at the end of scope"2c82f2bExempt CMAKE(CURRENT|PARENT)_LIST_FILE from usage6d7d449Ignore CLI warnings for ABI determination7740a73Only return local keys that are definedbef3aeeUse the API so that warnings can be tracked05cb0f4Check for unused variables in the dtor91c4c99Add test for unused warnings at the end of scopeca90f67Fix detection of unused variables when settingf7438caAdd test for unused detection via setting it995cfb0Don't warn if the variable wasn't definedaefc91dAdd test for usage checks via unseta8e97f8Remove VarRemoved code since it's been superceded59463efRework CheckVariableForUnused usagef117423Fix line lengths to be no more than 78e49a935Improve unused warning logice01e40cMark ARGC, ARGV*, and ARGN as useda17aff7Ignore CMAKE_MATCH_* variables for usage02a114dAdd method to allow variables to be marked as useda0b0d23CMAKE_DO_TRY_COMPILE is no longer usedae3eff3Fix the path used for ignoring system warnings056b441Fix missing case for usage of a variable980e048Factor out checks for unused variables83acb0aRemove now unused variables3801463Use built-ins for readability and maintainability8b52015Push the initialize and unused states when copying439877fBe consistent with single and double quotes4cf1706Add documentation for check-system-varsb74777fFix the spelling of the flag for warn-unused-varsb948120Change logic of flag to turn off cli unused checksf047a17Add test for uninitialized variables75bda38Add tests for unused command line variables300fc15Fix detection of system filesd784e6aRun the unused variables check on the final pass9efc057VariableWatch is not available when bootstrapping2e78224Add a missing comma to the warning message7499700Add a flag to warn about system filesfff9f6dRename flags again and use variablewatch for cli786e269Add warn-unused to the Qt interface636e6c4Default to marking things as used4ff0340Rename find-unused to warn-unusedd7999e9Rename strict-mode to warn-uninitializede141bc9Detect unused variablesd3e8eb5Add flags to detect unused variablesf332e14Complete strict-mode checks for uninitialized vars52f9637Add method to get the local scope variablesf794d58Make --strict-mode option, and integrate with cmake-gui48b5b85Add a warning when variables are used uninitialized.cd626eaFor macros make sure the FilePath points to a valid pointer in the args.
This commit is contained in:
@@ -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 "
|
||||
|
||||
60
Tests/ArgumentExpansion/CMakeLists.txt
Normal file
60
Tests/ArgumentExpansion/CMakeLists.txt
Normal file
@@ -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"
|
||||
|
||||
4
Tests/VariableUnusedViaSet/CMakeLists.txt
Normal file
4
Tests/VariableUnusedViaSet/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
set(UNUSED_VARIABLE)
|
||||
# Warning should occur here
|
||||
set(UNUSED_VARIABLE "Usage")
|
||||
message(STATUS "${UNUSED_VARIABLE}")
|
||||
8
Tests/VariableUnusedViaUnset/CMakeLists.txt
Normal file
8
Tests/VariableUnusedViaUnset/CMakeLists.txt
Normal file
@@ -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}")
|
||||
1
Tests/VariableUsage/CMakeLists.txt
Normal file
1
Tests/VariableUsage/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
message(STATUS "${USED_VARIABLE}")
|
||||
Reference in New Issue
Block a user